From 62d3f97e30a5b7262c6655c9a87686254daf5793 Mon Sep 17 00:00:00 2001 From: Frank Meyer Date: Tue, 21 Jul 2015 14:07:23 +0200 Subject: [PATCH 001/135] dded the ability to enable gridlines and axislabels on charts added options 'showAxisLabels', 'showGridX', 'showGridY' to charts style element --- samples/Sample_32_Chart.php | 8 +- src/PhpWord/Style/Chart.php | 90 ++++++++++++++++++++++ src/PhpWord/Writer/Word2007/Part/Chart.php | 9 ++- 3 files changed, 103 insertions(+), 4 deletions(-) diff --git a/samples/Sample_32_Chart.php b/samples/Sample_32_Chart.php index bc18392ef9..b6830fa029 100644 --- a/samples/Sample_32_Chart.php +++ b/samples/Sample_32_Chart.php @@ -22,11 +22,16 @@ $series1 = array(1, 3, 2, 5, 4); $series2 = array(3, 1, 7, 2, 6); $series3 = array(8, 3, 2, 5, 4); +$showGridLines = false; +$showAxisLabels = false; foreach ($chartTypes as $chartType) { $section->addTitle(ucfirst($chartType), 2); $chart = $section->addChart($chartType, $categories, $series1); $chart->getStyle()->setWidth(Converter::inchToEmu(2.5))->setHeight(Converter::inchToEmu(2)); + $chart->getStyle()->setShowGridX($showGridLines); + $chart->getStyle()->setShowGridY($showGridLines); + $chart->getStyle()->setShowAxisLabels($showAxisLabels); if (in_array($chartType, $twoSeries)) { $chart->addSeries($categories, $series2); } @@ -43,7 +48,8 @@ $chartTypes = array('pie', 'bar', 'column', 'line', 'area'); $multiSeries = array('bar', 'column', 'line', 'area'); -$style = array('width' => Converter::cmToEmu(5), 'height' => Converter::cmToEmu(4), '3d' => true); +$style = array('width' => Converter::cmToEmu(5), 'height' => Converter::cmToEmu(4), '3d' => true, + 'showAxisLabels' => $showAxisLabels, 'showGridX' => $showGridLines, 'showGridY' => $showGridLines); foreach ($chartTypes as $chartType) { $section->addTitle(ucfirst($chartType), 2); $chart = $section->addChart($chartType, $categories, $series1, $style); diff --git a/src/PhpWord/Style/Chart.php b/src/PhpWord/Style/Chart.php index 13b72a33f5..112a0a4a3b 100644 --- a/src/PhpWord/Style/Chart.php +++ b/src/PhpWord/Style/Chart.php @@ -46,6 +46,27 @@ class Chart extends AbstractStyle */ private $is3d = false; + /** + * Show labels for axis + * + * @var bool + */ + private $showAxisLabels = false; + + /** + * Show Gridlines for Y-Axis + * + * @var bool + */ + private $gridY = false; + + /** + * Show Gridlines for X-Axis + * + * @var bool + */ + private $gridX = false; + /** * Create a new instance * @@ -124,4 +145,73 @@ public function set3d($value = true) return $this; } + + /** + * Show labels for axis + * + * @return bool + */ + public function showAxisLabels() + { + return $this->showAxisLabels; + } + + /** + * Set show Gridlines for Y-Axis + * + * @param bool $value + * @return self + */ + public function setShowAxisLabels($value = true) + { + $this->showAxisLabels = $this->setBoolVal($value, $this->showAxisLabels); + + return $this; + } + + /** + * Show Gridlines for Y-Axis + * + * @return bool + */ + public function showGridY() + { + return $this->gridY; + } + + /** + * Set show Gridlines for Y-Axis + * + * @param bool $value + * @return self + */ + public function setShowGridY($value = true) + { + $this->gridY = $this->setBoolVal($value, $this->gridY); + + return $this; + } + + /** + * Show Gridlines for X-Axis + * + * @return bool + */ + public function showGridX() + { + return $this->gridX; + } + + /** + * Set show Gridlines for X-Axis + * + * @param bool $value + * @return self + */ + public function setShowGridX($value = true) + { + $this->gridX = $this->setBoolVal($value, $this->gridX); + + return $this; + } } diff --git a/src/PhpWord/Writer/Word2007/Part/Chart.php b/src/PhpWord/Writer/Word2007/Part/Chart.php index 8423762c30..abc2962ab0 100644 --- a/src/PhpWord/Writer/Word2007/Part/Chart.php +++ b/src/PhpWord/Writer/Word2007/Part/Chart.php @@ -264,6 +264,7 @@ private function writeSeriesItem(XMLWriter $xmlWriter, $type, $values) */ private function writeAxis(XMLWriter $xmlWriter, $type) { + $style = $this->element->getStyle(); $types = array( 'cat' => array('c:catAx', 1, 'b', 2), 'val' => array('c:valAx', 2, 'l', 1), @@ -273,7 +274,7 @@ private function writeAxis(XMLWriter $xmlWriter, $type) $xmlWriter->startElement($axisType); $xmlWriter->writeElementBlock('c:axId', 'val', $axisId); - $xmlWriter->writeElementBlock('c:axPos', 'val', $axisPos); + $xmlWriter->writeElementBlock('c:axPos', 'val', $axisPos); $xmlWriter->writeElementBlock('c:crossAx', 'val', $axisCross); $xmlWriter->writeElementBlock('c:auto', 'val', 1); @@ -281,10 +282,12 @@ private function writeAxis(XMLWriter $xmlWriter, $type) $xmlWriter->writeElementBlock('c:delete', 'val', 0); $xmlWriter->writeElementBlock('c:majorTickMark', 'val', 'none'); $xmlWriter->writeElementBlock('c:minorTickMark', 'val', 'none'); - $xmlWriter->writeElementBlock('c:tickLblPos', 'val', 'none'); // nextTo + if($style->showAxisLabels()) + $xmlWriter->writeElementBlock('c:tickLblPos', 'val', 'nextTo'); + else $xmlWriter->writeElementBlock('c:tickLblPos', 'val', 'none'); $xmlWriter->writeElementBlock('c:crosses', 'val', 'autoZero'); } - if (isset($this->options['radar'])) { + if (isset($this->options['radar']) || ($type == "cat" && $style->showGridX()) || ($type == "val" && $style->showGridY())) { $xmlWriter->writeElement('c:majorGridlines'); } From 3a251770e89d0052b50c6b41551291692d46d559 Mon Sep 17 00:00:00 2001 From: Frank Meyer Date: Tue, 21 Jul 2015 14:56:29 +0200 Subject: [PATCH 002/135] Removed complains of php-codesniffer removed whitespace changed inline if statement --- src/PhpWord/Writer/Word2007/Part/Chart.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/PhpWord/Writer/Word2007/Part/Chart.php b/src/PhpWord/Writer/Word2007/Part/Chart.php index abc2962ab0..56df10271f 100644 --- a/src/PhpWord/Writer/Word2007/Part/Chart.php +++ b/src/PhpWord/Writer/Word2007/Part/Chart.php @@ -274,7 +274,7 @@ private function writeAxis(XMLWriter $xmlWriter, $type) $xmlWriter->startElement($axisType); $xmlWriter->writeElementBlock('c:axId', 'val', $axisId); - $xmlWriter->writeElementBlock('c:axPos', 'val', $axisPos); + $xmlWriter->writeElementBlock('c:axPos', 'val', $axisPos); $xmlWriter->writeElementBlock('c:crossAx', 'val', $axisCross); $xmlWriter->writeElementBlock('c:auto', 'val', 1); @@ -282,9 +282,12 @@ private function writeAxis(XMLWriter $xmlWriter, $type) $xmlWriter->writeElementBlock('c:delete', 'val', 0); $xmlWriter->writeElementBlock('c:majorTickMark', 'val', 'none'); $xmlWriter->writeElementBlock('c:minorTickMark', 'val', 'none'); - if($style->showAxisLabels()) + if($style->showAxisLabels()) { $xmlWriter->writeElementBlock('c:tickLblPos', 'val', 'nextTo'); - else $xmlWriter->writeElementBlock('c:tickLblPos', 'val', 'none'); + } + else { + $xmlWriter->writeElementBlock('c:tickLblPos', 'val', 'none'); + } $xmlWriter->writeElementBlock('c:crosses', 'val', 'autoZero'); } if (isset($this->options['radar']) || ($type == "cat" && $style->showGridX()) || ($type == "val" && $style->showGridY())) { From a6528471c26f280cb74cd1add9e8ae1c5676956a Mon Sep 17 00:00:00 2001 From: Frank Meyer Date: Tue, 21 Jul 2015 15:11:34 +0200 Subject: [PATCH 003/135] changed if statement due to error in codesniffer --- src/PhpWord/Writer/Word2007/Part/Chart.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/PhpWord/Writer/Word2007/Part/Chart.php b/src/PhpWord/Writer/Word2007/Part/Chart.php index 56df10271f..92d61e6eac 100644 --- a/src/PhpWord/Writer/Word2007/Part/Chart.php +++ b/src/PhpWord/Writer/Word2007/Part/Chart.php @@ -282,10 +282,9 @@ private function writeAxis(XMLWriter $xmlWriter, $type) $xmlWriter->writeElementBlock('c:delete', 'val', 0); $xmlWriter->writeElementBlock('c:majorTickMark', 'val', 'none'); $xmlWriter->writeElementBlock('c:minorTickMark', 'val', 'none'); - if($style->showAxisLabels()) { + if ($style->showAxisLabels()) { $xmlWriter->writeElementBlock('c:tickLblPos', 'val', 'nextTo'); - } - else { + } else { $xmlWriter->writeElementBlock('c:tickLblPos', 'val', 'none'); } $xmlWriter->writeElementBlock('c:crosses', 'val', 'autoZero'); From cb034879b40c0aa1faee6a699eb50ce48cbf8c4d Mon Sep 17 00:00:00 2001 From: Russ Date: Thu, 6 Aug 2015 12:50:31 -0500 Subject: [PATCH 004/135] Add Date Formats to Field Element Fix a typo (d-M-yyy H:mm), and expand the list of valid date formats. --- src/PhpWord/Element/Field.php | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/PhpWord/Element/Field.php b/src/PhpWord/Element/Field.php index 1eaa6f242f..b277494e0e 100644 --- a/src/PhpWord/Element/Field.php +++ b/src/PhpWord/Element/Field.php @@ -47,9 +47,23 @@ class Field extends AbstractElement ), 'DATE'=>array( 'properties'=> array( - 'dateformat' =>array('d-M-yyyy', 'dddd d MMMM yyyy', 'd MMMM yyyy', 'd-M-yy', 'yyyy-MM-dd', - 'd-MMM-yy', 'd/M/yyyy', 'd MMM. yy', 'd/M/yy', 'MMM-yy', 'd-M-yyy H:mm', 'd-M-yyyy H:mm:ss', - 'h:mm am/pm', 'h:mm:ss am/pm', 'HH:mm', 'HH:mm:ss') + 'dateformat' =>array( + /* Generic formats */ + 'yyyy-MM-dd', 'yyyy-MM', 'MMM-yy', 'MMM-yyyy', 'h:mm am/pm', 'h:mm:ss am/pm', 'HH:mm', 'HH:mm:ss', + + /* Day-Month-Year formats */ + 'dddd d MMMM yyyy', 'd MMMM yyyy', 'd-MMM-yy', 'd MMM. yy', + 'd-M-yy', 'd-M-yy H:mm', 'd-M-yy H:mm:ss', 'd-M-yy H:mm am/pm', 'd-M-yy H:mm:ss am/pm', 'd-M-yy HH:mm', 'd-M-yy HH:mm:ss', + 'd/M/yy', 'd/M/yy H:mm', 'd/M/yy H:mm:ss', 'd/M/yy H:mm am/pm', 'd/M/yy H:mm:ss am/pm', 'd/M/yy HH:mm', 'd/M/yy HH:mm:ss', + 'd-M-yyyy', 'd-M-yyyy H:mm', 'd-M-yyyy H:mm:ss', 'd-M-yyyy H:mm am/pm', 'd-M-yyyy H:mm:ss am/pm', 'd-M-yyyy HH:mm', 'd-M-yyyy HH:mm:ss', + 'd/M/yyyy', 'd/M/yyyy H:mm', 'd/M/yyyy H:mm:ss', 'd/M/yyyy H:mm am/pm', 'd/M/yyyy H:mm:ss am/pm', 'd/M/yyyy HH:mm', 'd/M/yyyy HH:mm:ss', + + /* Month-Day-Year formats */ + 'dddd, MMMM d yyyy', 'MMMM d yyyy', 'MMM-d-yy', 'MMM. d yy', + 'M-d-yy', 'M-d-yy H:mm', 'M-d-yy H:mm:ss', 'M-d-yy H:mm am/pm', 'M-d-yy H:mm:ss am/pm', 'M-d-yy HH:mm', 'M-d-yy HH:mm:ss', + 'M/d/yy', 'M/d/yy H:mm', 'M/d/yy H:mm:ss', 'M/d/yy H:mm am/pm', 'M/d/yy H:mm:ss am/pm', 'M/d/yy HH:mm', 'M/d/yy HH:mm:ss', + 'M-d-yyyy', 'M-d-yyyy H:mm', 'M-d-yyyy H:mm:ss', 'M-d-yyyy H:mm am/pm', 'M-d-yyyy H:mm:ss am/pm', 'M-d-yyyy HH:mm', 'M-d-yyyy HH:mm:ss', + 'M/d/yyyy', 'M/d/yyyy H:mm', 'M/d/yyyy H:mm:ss', 'M/d/yyyy H:mm am/pm', 'M/d/yyyy H:mm:ss am/pm', 'M/d/yyyy HH:mm', 'M/d/yyyy HH:mm:ss') ), 'options'=>array('PreserveFormat', 'LunarCalendar', 'SakaEraCalendar', 'LastUsedFormat') ) From a9398e32c7f6f5371693878509da50c7eb0ea27c Mon Sep 17 00:00:00 2001 From: Russ Date: Thu, 6 Aug 2015 13:22:01 -0500 Subject: [PATCH 005/135] Fix Hour Casing for Intended Formats to Work Correctly Time formats should either be "h" or "HH". There were some formats which were incorrectly specified as "H". --- src/PhpWord/Element/Field.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/PhpWord/Element/Field.php b/src/PhpWord/Element/Field.php index b277494e0e..4e8195b3a7 100644 --- a/src/PhpWord/Element/Field.php +++ b/src/PhpWord/Element/Field.php @@ -53,17 +53,17 @@ class Field extends AbstractElement /* Day-Month-Year formats */ 'dddd d MMMM yyyy', 'd MMMM yyyy', 'd-MMM-yy', 'd MMM. yy', - 'd-M-yy', 'd-M-yy H:mm', 'd-M-yy H:mm:ss', 'd-M-yy H:mm am/pm', 'd-M-yy H:mm:ss am/pm', 'd-M-yy HH:mm', 'd-M-yy HH:mm:ss', - 'd/M/yy', 'd/M/yy H:mm', 'd/M/yy H:mm:ss', 'd/M/yy H:mm am/pm', 'd/M/yy H:mm:ss am/pm', 'd/M/yy HH:mm', 'd/M/yy HH:mm:ss', - 'd-M-yyyy', 'd-M-yyyy H:mm', 'd-M-yyyy H:mm:ss', 'd-M-yyyy H:mm am/pm', 'd-M-yyyy H:mm:ss am/pm', 'd-M-yyyy HH:mm', 'd-M-yyyy HH:mm:ss', - 'd/M/yyyy', 'd/M/yyyy H:mm', 'd/M/yyyy H:mm:ss', 'd/M/yyyy H:mm am/pm', 'd/M/yyyy H:mm:ss am/pm', 'd/M/yyyy HH:mm', 'd/M/yyyy HH:mm:ss', + 'd-M-yy', 'd-M-yy h:mm', 'd-M-yy h:mm:ss', 'd-M-yy h:mm am/pm', 'd-M-yy h:mm:ss am/pm', 'd-M-yy HH:mm', 'd-M-yy HH:mm:ss', + 'd/M/yy', 'd/M/yy h:mm', 'd/M/yy h:mm:ss', 'd/M/yy h:mm am/pm', 'd/M/yy h:mm:ss am/pm', 'd/M/yy HH:mm', 'd/M/yy HH:mm:ss', + 'd-M-yyyy', 'd-M-yyyy h:mm', 'd-M-yyyy h:mm:ss', 'd-M-yyyy h:mm am/pm', 'd-M-yyyy h:mm:ss am/pm', 'd-M-yyyy HH:mm', 'd-M-yyyy HH:mm:ss', + 'd/M/yyyy', 'd/M/yyyy h:mm', 'd/M/yyyy h:mm:ss', 'd/M/yyyy h:mm am/pm', 'd/M/yyyy h:mm:ss am/pm', 'd/M/yyyy HH:mm', 'd/M/yyyy HH:mm:ss', /* Month-Day-Year formats */ 'dddd, MMMM d yyyy', 'MMMM d yyyy', 'MMM-d-yy', 'MMM. d yy', - 'M-d-yy', 'M-d-yy H:mm', 'M-d-yy H:mm:ss', 'M-d-yy H:mm am/pm', 'M-d-yy H:mm:ss am/pm', 'M-d-yy HH:mm', 'M-d-yy HH:mm:ss', - 'M/d/yy', 'M/d/yy H:mm', 'M/d/yy H:mm:ss', 'M/d/yy H:mm am/pm', 'M/d/yy H:mm:ss am/pm', 'M/d/yy HH:mm', 'M/d/yy HH:mm:ss', - 'M-d-yyyy', 'M-d-yyyy H:mm', 'M-d-yyyy H:mm:ss', 'M-d-yyyy H:mm am/pm', 'M-d-yyyy H:mm:ss am/pm', 'M-d-yyyy HH:mm', 'M-d-yyyy HH:mm:ss', - 'M/d/yyyy', 'M/d/yyyy H:mm', 'M/d/yyyy H:mm:ss', 'M/d/yyyy H:mm am/pm', 'M/d/yyyy H:mm:ss am/pm', 'M/d/yyyy HH:mm', 'M/d/yyyy HH:mm:ss') + 'M-d-yy', 'M-d-yy h:mm', 'M-d-yy h:mm:ss', 'M-d-yy h:mm am/pm', 'M-d-yy h:mm:ss am/pm', 'M-d-yy HH:mm', 'M-d-yy HH:mm:ss', + 'M/d/yy', 'M/d/yy h:mm', 'M/d/yy h:mm:ss', 'M/d/yy h:mm am/pm', 'M/d/yy h:mm:ss am/pm', 'M/d/yy HH:mm', 'M/d/yy HH:mm:ss', + 'M-d-yyyy', 'M-d-yyyy h:mm', 'M-d-yyyy h:mm:ss', 'M-d-yyyy h:mm am/pm', 'M-d-yyyy h:mm:ss am/pm', 'M-d-yyyy HH:mm', 'M-d-yyyy HH:mm:ss', + 'M/d/yyyy', 'M/d/yyyy h:mm', 'M/d/yyyy h:mm:ss', 'M/d/yyyy h:mm am/pm', 'M/d/yyyy h:mm:ss am/pm', 'M/d/yyyy HH:mm', 'M/d/yyyy HH:mm:ss') ), 'options'=>array('PreserveFormat', 'LunarCalendar', 'SakaEraCalendar', 'LastUsedFormat') ) From adfcc62e644f1fe6ce24f5392803cebdf9a02760 Mon Sep 17 00:00:00 2001 From: Sam Sullivan Date: Mon, 11 Apr 2016 12:48:43 -0500 Subject: [PATCH 006/135] imagesavealpha() in Writer\AbstractWriter --- src/PhpWord/Writer/AbstractWriter.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/PhpWord/Writer/AbstractWriter.php b/src/PhpWord/Writer/AbstractWriter.php index 55b2023294..c6b64c280e 100644 --- a/src/PhpWord/Writer/AbstractWriter.php +++ b/src/PhpWord/Writer/AbstractWriter.php @@ -360,6 +360,10 @@ protected function addFilesToPackage(ZipArchive $zip, $elements) // Retrive GD image content or get local media if (isset($element['isMemImage']) && $element['isMemImage']) { $image = call_user_func($element['createFunction'], $element['source']); + if ($element['imageType'] === 'image/png') { + // PNG images need to preserve alpha channel information + imagesavealpha($image, true); + } ob_start(); call_user_func($element['imageFunction'], $image); $imageContents = ob_get_contents(); From f4ec74a4c5338f1df4a3dbb58a19b946ab627005 Mon Sep 17 00:00:00 2001 From: Sam Sullivan Date: Mon, 11 Apr 2016 12:49:18 -0500 Subject: [PATCH 007/135] imagesavealpha() in Element\Image --- src/PhpWord/Element/Image.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/PhpWord/Element/Image.php b/src/PhpWord/Element/Image.php index f5cc7ccccf..64ddfd86ed 100644 --- a/src/PhpWord/Element/Image.php +++ b/src/PhpWord/Element/Image.php @@ -335,6 +335,10 @@ public function getImageStringData($base64 = false) // Read image binary data and convert to hex/base64 string if ($this->sourceType == self::SOURCE_GD) { $imageResource = call_user_func($this->imageCreateFunc, $actualSource); + if ($this->imageType === 'image/png') { + // PNG images need to preserve alpha channel information + imagesavealpha($imageResource, true); + } ob_start(); call_user_func($this->imageFunc, $imageResource); $imageBinary = ob_get_contents(); From 133b727f592eef4c47d099f543fcdbe45833bc42 Mon Sep 17 00:00:00 2001 From: ale rimoldi Date: Mon, 25 Jul 2016 10:11:52 +0200 Subject: [PATCH 008/135] table->setStretch() optionally avoids the table to stretch to the page width (only for word output) --- src/PhpWord/Style/Table.php | 33 +++++++++++++++++++++ src/PhpWord/Writer/Word2007/Style/Table.php | 15 ++++++++++ 2 files changed, 48 insertions(+) diff --git a/src/PhpWord/Style/Table.php b/src/PhpWord/Style/Table.php index 24f5066777..4b411cdcf0 100644 --- a/src/PhpWord/Style/Table.php +++ b/src/PhpWord/Style/Table.php @@ -28,6 +28,8 @@ class Table extends Border const WIDTH_AUTO = 'auto'; // Automatically determined width const WIDTH_PERCENT = 'pct'; // Width in fiftieths (1/50) of a percent (1% = 50 unit) const WIDTH_TWIP = 'dxa'; // Width in twentieths (1/20) of a point (twip) + const STRETCH_AUTO = 'autofit'; // Automatically stretch the table to fit the page width + const STRETCH_FIXED = 'fixed'; // Do not stretch the table to fit the page width /** * Is this a first row style? @@ -121,6 +123,11 @@ class Table extends Border */ private $unit = self::WIDTH_AUTO; + /** + * @var string Stretch the table to the page width + */ + private $stretch = self::STRETCH_AUTO; + /** * Create new table style * @@ -563,6 +570,32 @@ public function setUnit($value = null) return $this; } + /** + * Get stretch + * + * @return string + */ + public function getStretch() + { + return $this->stretch; + } + + /** + * Set stretch + * + * Stretch the table to the page width + * + * @param string $value + * @return self + */ + public function setStretch($value = null) + { + $enum = array(self::STRETCH_AUTO, self::STRETCH_FIXED); + $this->stretch = $this->setEnumVal($value, $enum, $this->stretch); + + return $this; + } + /** * Get table style only property by checking if it's a firstRow * diff --git a/src/PhpWord/Writer/Word2007/Style/Table.php b/src/PhpWord/Writer/Word2007/Style/Table.php index 8bbad107c3..b3686f9091 100644 --- a/src/PhpWord/Writer/Word2007/Style/Table.php +++ b/src/PhpWord/Writer/Word2007/Style/Table.php @@ -74,6 +74,7 @@ private function writeStyle(XMLWriter $xmlWriter, TableStyle $style) $styleWriter->write(); $this->writeWidth($xmlWriter, $style->getWidth(), $style->getUnit()); + $this->writeLayout($xmlWriter, $style->getStretch()); $this->writeMargin($xmlWriter, $style); $this->writeBorder($xmlWriter, $style); @@ -104,6 +105,20 @@ private function writeWidth(XMLWriter $xmlWriter, $width, $unit) $xmlWriter->endElement(); // w:tblW } + /** + * Enable/Disable automatic resizing of the table + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param string $layout autofit / fixed + * @return void + */ + private function writeLayout(XMLWriter $xmlWriter, $stretch) + { + $xmlWriter->startElement('w:tblLayout'); + $xmlWriter->writeAttribute('w:type', $stretch); + $xmlWriter->endElement(); // w:tblLayout + } + /** * Write margin. * From 8ed3cacfe8d6ddb9c44843ed981d0bede3a9aab9 Mon Sep 17 00:00:00 2001 From: Gabriel Caruso Date: Tue, 16 Jan 2018 20:19:54 -0200 Subject: [PATCH 009/135] Refactoring --- src/PhpWord/Writer/Word2007/Element/Container.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/Writer/Word2007/Element/Container.php b/src/PhpWord/Writer/Word2007/Element/Container.php index 47dae29be0..b6d1145cf9 100644 --- a/src/PhpWord/Writer/Word2007/Element/Container.php +++ b/src/PhpWord/Writer/Word2007/Element/Container.php @@ -46,7 +46,7 @@ public function write() return; } $containerClass = substr(get_class($container), strrpos(get_class($container), '\\') + 1); - $withoutP = in_array($containerClass, array('TextRun', 'Footnote', 'Endnote', 'ListItemRun')) ? true : false; + $withoutP = in_array($containerClass, array('TextRun', 'Footnote', 'Endnote', 'ListItemRun')); $xmlWriter = $this->getXmlWriter(); // Loop through elements From caba7e238ff05c2cfd2a438d3f4cb77ee235623e Mon Sep 17 00:00:00 2001 From: Samuel Laulhau Date: Wed, 31 Jan 2018 10:17:40 +0100 Subject: [PATCH 010/135] Delete VERSION Delete VERSION file since it's outdated so not usefull anymore --- VERSION | 1 - 1 file changed, 1 deletion(-) delete mode 100644 VERSION diff --git a/VERSION b/VERSION deleted file mode 100644 index 51de3305bb..0000000000 --- a/VERSION +++ /dev/null @@ -1 +0,0 @@ -0.13.0 \ No newline at end of file From 8a9a4784d91da529ab327670f6712f719541491a Mon Sep 17 00:00:00 2001 From: Sami Mussbach Date: Thu, 1 Feb 2018 13:58:08 +0100 Subject: [PATCH 011/135] add (failing) test and correct documentation sample to valid HTML --- samples/Sample_26_Html.php | 11 +++++---- tests/PhpWord/Shared/HtmlTest.php | 37 +++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/samples/Sample_26_Html.php b/samples/Sample_26_Html.php index 69d9d1310e..b05f8d0803 100644 --- a/samples/Sample_26_Html.php +++ b/samples/Sample_26_Html.php @@ -29,10 +29,13 @@
  1. List 2 item 1
  2. List 2 item 2
  3. -
      -
    1. sub list 1
    2. -
    3. sub list 2
    4. -
    +
  4. +
      +
    1. sub list 1
    2. +
    3. sub list 2
    4. +
    +
  5. +
  6. List 2 item 3
    1. sub list 1, restarts with a
    2. diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index 6122924ff0..936c35f981 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -272,6 +272,43 @@ public function tesOrderedListNumbering() $this->assertNotEquals($firstListnumId, $secondListnumId); } + /** + * Tests parsing of nested ul/li + */ + public function testOrderedNestedListNumbering() + { + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + $html = '
        +
      1. List 1 item 1
      2. +
      3. List 1 item 2
      4. +
      +

      Some Text

      +
        +
      1. List 2 item 1
      2. +
      3. +
          +
        1. sub list 1
        2. +
        3. sub list 2
        4. +
        +
      4. +
      '; + Html::addHtml($section, $html, false, false); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + echo $doc->printXml(); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:pPr/w:numPr/w:numId')); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:t')); + + $this->assertEquals('List 1 item 1', $doc->getElement('/w:document/w:body/w:p[1]/w:r/w:t')->nodeValue); + $this->assertEquals('List 2 item 1', $doc->getElement('/w:document/w:body/w:p[4]/w:r/w:t')->nodeValue); + + $firstListnumId = $doc->getElementAttribute('/w:document/w:body/w:p[1]/w:pPr/w:numPr/w:numId', 'w:val'); + $secondListnumId = $doc->getElementAttribute('/w:document/w:body/w:p[4]/w:pPr/w:numPr/w:numId', 'w:val'); + + $this->assertNotEquals($firstListnumId, $secondListnumId); + } + /** * Tests parsing of ul/li */ From e0096dba084c767582e15917bf5b357c790a5995 Mon Sep 17 00:00:00 2001 From: Sami Mussbach Date: Thu, 1 Feb 2018 14:12:56 +0100 Subject: [PATCH 012/135] fix typo in test method name --- tests/PhpWord/Shared/HtmlTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index 6122924ff0..97a8fb156f 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -243,7 +243,7 @@ public function testParseList() /** * Tests parsing of ul/li */ - public function tesOrderedListNumbering() + public function testOrderedListNumbering() { $phpWord = new \PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); From 4105a9aad1bd8e08cd3e7d5a74810a9e73f80fd4 Mon Sep 17 00:00:00 2001 From: Nicolas Dermine Date: Fri, 2 Feb 2018 16:19:21 +0100 Subject: [PATCH 013/135] improve `cloneBlock` regex it wrongly matched `\${' . $blockname . '}<\/w:.*?p>)(.*)()/is', + '/(<\?xml.*)(\${' . $blockname . '}<\/w:.*?p>)(.*)()/is', $this->tempDocumentMainPart, $matches ); diff --git a/tests/PhpWord/TemplateProcessorTest.php b/tests/PhpWord/TemplateProcessorTest.php index 7b064ef7b8..122ed5b613 100644 --- a/tests/PhpWord/TemplateProcessorTest.php +++ b/tests/PhpWord/TemplateProcessorTest.php @@ -223,4 +223,56 @@ public function testCloneDeleteBlock() unlink($docName); $this->assertTrue($docFound); } + + /** + * @covers ::cloneBlock + * @test + */ + public function cloneBlockCanCloneABlockTwice() + { + // create template with placeholders and block + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $documentElements = array( + 'Title: ${title}', + '${subreport}', + '${subreport.id}: ${subreport.text}. ', + '${/subreport}', + ); + foreach ($documentElements as $documentElement) { + $section->addText($documentElement); + } + $objWriter = IOFactory::createWriter($phpWord); + $templatePath = 'test.docx'; + $objWriter->save($templatePath); + + // replace placeholders and save the file + $templateProcessor = new TemplateProcessor($templatePath); + $templateProcessor->setValue('title', 'Some title'); + $templateProcessor->cloneBlock('subreport', 2); + $templateProcessor->setValue('subreport.id', '123', 1); + $templateProcessor->setValue('subreport.text', 'Some text', 1); + $templateProcessor->setValue('subreport.id', '456', 1); + $templateProcessor->setValue('subreport.text', 'Some other text', 1); + $templateProcessor->saveAs($templatePath); + + // assert the block has been cloned twice + // and the placeholders have been replaced correctly + $phpWord = IOFactory::load($templatePath); + $sections = $phpWord->getSections(); + $actualElements = $sections[0]->getElements(); + unlink($templatePath); + $expectedElements = array( + 'Title: Some title', + '123: Some text. ', + '456: Some other text. ', + ); + $this->assertCount(count($expectedElements), $actualElements); + foreach ($expectedElements as $i => $expectedElement) { + $this->assertEquals( + $expectedElement, + $actualElements[$i]->getText() + ); + } + } } From edd9617c03888ce4dd2e28c2fcacfad98194f4fc Mon Sep 17 00:00:00 2001 From: Nicolas Dermine Date: Sun, 4 Feb 2018 08:42:38 +0100 Subject: [PATCH 014/135] fix typo --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 335ad2d519..e62f2e6f04 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,7 +6,7 @@ We want to create a high quality document writer and reader library that people - **Be brief, but be bold**. State your issues briefly. But speak out your ideas loudly, even if you can't or don't know how to implement it right away. The world will be better with limitless innovations. - **Follow PHP-FIG standards**. We follow PHP Standards Recommendations (PSRs) by [PHP Framework Interoperability Group](http://www.php-fig.org/). If you're not familiar with these standards, please, [familiarize yourself now](https://github.com/php-fig/fig-standards). Also, please, use [PHPCodeSniffer](http://pear.php.net/package/PHP_CodeSniffer/) to validate your code against PSRs. -- **Test your code**. Nobody else knows your code better than you. So, it's completely yours mission to test the changes you made before pull request submission. We use [PHPUnit](https://phpunit.de/) for our testing purposes and recommend you using this tool too. [Here](https://phpunit.de/presentations.html) you can find PHPUnit best practices and additional information on effective unit testing, which helps us making PHPWord better day to day. Do not hesitate to smoke it carefully. It's a great investment in quality of your work, and it saves you years of life. +- **Test your code**. Nobody else knows your code better than you. So, it's completely your mission to test the changes you made before pull request submission. We use [PHPUnit](https://phpunit.de/) for our testing purposes and recommend you using this tool too. [Here](https://phpunit.de/presentations.html) you can find PHPUnit best practices and additional information on effective unit testing, which helps us making PHPWord better day to day. Do not hesitate to smoke it carefully. It's a great investment in quality of your work, and it saves you years of life. - **Request pull in separate branch**. Do not submit your request to the master branch. But create a separate branch named specifically for the issue that you addressed. Read [GitHub manual](https://help.github.com/articles/using-pull-requests) to find out more about this. If you are new to GitHub, read [this short manual](https://help.github.com/articles/fork-a-repo) to get yourself familiar with forks and how git works in general. [This video](http://www.youtube.com/watch?v=-zvHQXnBO6c) explains how to synchronize your Github Fork with the Branch of PHPWord. That's it. Thank you for your interest in PHPWord, and welcome! From 46a5f96d3b5104aaa6b016e5df0730e4382058e7 Mon Sep 17 00:00:00 2001 From: troosan Date: Tue, 6 Feb 2018 23:16:32 +0100 Subject: [PATCH 015/135] fix parsing of table and p inside table cells --- CHANGELOG.md | 2 ++ samples/Sample_26_Html.php | 16 +++++++-- src/PhpWord/Shared/Html.php | 38 +++++++++++++++++++++- src/PhpWord/Writer/Word2007/Style/Font.php | 4 +++ tests/PhpWord/Shared/HtmlTest.php | 6 ++-- 5 files changed, 60 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6f8b2da00..fca2922ce0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,9 +8,11 @@ v0.15.0 (?? ??? 2018) ### Added - Parsing of "align" HTML attribute - @troosan #1231 - Parse formatting inside HTML lists - @troosan @samimussbach #1239 #945 #1215 #508 +- Parsing of CSS `direction` instruction, HTML `lang` attribute, formatting inside table cell - @troosan # ### Fixed - fix reading of docx default style - @troosan #1238 +- fix the size unit of when parsing html images - @troosan #1254 diff --git a/samples/Sample_26_Html.php b/samples/Sample_26_Html.php index 69d9d1310e..d54d548cd1 100644 --- a/samples/Sample_26_Html.php +++ b/samples/Sample_26_Html.php @@ -7,11 +7,13 @@ $section = $phpWord->addSection(); $html = '

      Adding element via HTML

      '; -$html .= '

      Some well formed HTML snippet needs to be used

      '; +$html .= '

      Some well-formed HTML snippet needs to be used

      '; $html .= '

      With for example some1 inline formatting1

      '; $html .= '

      A link to Read the docs

      '; +$html .= '

      היי, זה פסקה מימין לשמאל

      '; + $html .= '

      Unordered (bulleted) list:

      '; $html .= '
      • Item 1
      • Item 2
        • Item 2.1
        • Item 2.1
      '; @@ -65,10 +67,20 @@ 12 - 456 + This is bold text6 '; +$html .= '

      Table inside another table:

      '; +$html .= ' + + +
      + + +
      column 1column 2
      +
      Cell in parent table
      '; + \PhpOffice\PhpWord\Shared\Html::addHtml($section, $html, false, false); // Save file diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 0f5f446aee..2eeaae8b5a 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -31,6 +31,7 @@ class Html { private static $listIndex = 0; + private static $xpath; /** * Add HTML parts. @@ -65,6 +66,7 @@ public static function addHtml($element, $html, $fullHTML = false, $preserveWhit $dom = new \DOMDocument(); $dom->preserveWhiteSpace = $preserveWhiteSpace; $dom->loadXML($html); + self::$xpath = new \DOMXpath($dom); $node = $dom->getElementsByTagName('body'); self::parseNode($node->item(0), $element); @@ -89,6 +91,10 @@ protected static function parseInlineStyle($node, $styles = array()) break; case 'align': $styles['alignment'] = self::mapAlign($attribute->value); + break; + case 'lang': + $styles['lang'] = $attribute->value; + break; } } } @@ -343,8 +349,33 @@ private static function parseCell($node, $element, &$styles) if (!empty($colspan)) { $cellStyles['gridSpan'] = $colspan - 0; } + $cell = $element->addCell(null, $cellStyles); + + if (self::shouldAddTextRun($node)) { + return $cell->addTextRun(self::parseInlineStyle($node, $styles['paragraph'])); + } + + return $cell; + } + + /** + * Checks if $node contains an HTML element that cannot be added to TextRun + * + * @param \DOMNode $node + * @return bool Returns true if the node contains an HTML element that cannot be added to TextRun + */ + private static function shouldAddTextRun(\DOMNode $node) + { + if (!$node->hasChildNodes()) { + return false; + } + + $containsBlockElement = self::$xpath->query('.//table|./p', $node)->length > 0; + if ($containsBlockElement) { + return false; + } - return $element->addCell(null, $cellStyles); + return true; } /** @@ -469,6 +500,9 @@ private static function parseStyle($attribute, $styles) case 'text-align': $styles['alignment'] = self::mapAlign($cValue); break; + case 'direction': + $styles['rtl'] = $cValue === 'rtl'; + break; case 'font-size': $styles['size'] = Converter::cssToPoint($cValue); break; @@ -556,10 +590,12 @@ private static function parseImage($node, $element) case 'width': $width = $attribute->value; $style['width'] = $width; + $style['unit'] = \PhpOffice\PhpWord\Style\Image::UNIT_PX; break; case 'height': $height = $attribute->value; $style['height'] = $height; + $style['unit'] = \PhpOffice\PhpWord\Style\Image::UNIT_PX; break; case 'style': $styleattr = explode(';', $attribute->value); diff --git a/src/PhpWord/Writer/Word2007/Style/Font.php b/src/PhpWord/Writer/Word2007/Style/Font.php index 9c2714dc71..ecaad416c6 100644 --- a/src/PhpWord/Writer/Word2007/Style/Font.php +++ b/src/PhpWord/Writer/Word2007/Style/Font.php @@ -90,6 +90,10 @@ private function writeStyle() $xmlWriter->writeAttributeIf($language->getLatin() !== null, 'w:val', $language->getLatin()); $xmlWriter->writeAttributeIf($language->getEastAsia() !== null, 'w:eastAsia', $language->getEastAsia()); $xmlWriter->writeAttributeIf($language->getBidirectional() !== null, 'w:bidi', $language->getBidirectional()); + //if bidi is not set but we are writing RTL, write the latin language in the bidi tag + if ($style->isRTL() && $language->getBidirectional() === null && $language->getLatin() !== null) { + $xmlWriter->writeAttribute('w:bidi', $language->getLatin()); + } $xmlWriter->endElement(); } diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index 97a8fb156f..7d5f0b4c17 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -259,7 +259,7 @@ public function testOrderedListNumbering() Html::addHtml($section, $html, false, false); $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); - echo $doc->printXml(); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:pPr/w:numPr/w:numId')); $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:t')); @@ -336,8 +336,8 @@ public function testParseImage() $baseXpath = '/w:document/w:body/w:p/w:r'; $this->assertTrue($doc->elementExists($baseXpath . '/w:pict/v:shape')); - $this->assertStringMatchesFormat('%Swidth:150pt%S', $doc->getElementAttribute($baseXpath . '[1]/w:pict/v:shape', 'style')); - $this->assertStringMatchesFormat('%Sheight:200pt%S', $doc->getElementAttribute($baseXpath . '[1]/w:pict/v:shape', 'style')); + $this->assertStringMatchesFormat('%Swidth:150px%S', $doc->getElementAttribute($baseXpath . '[1]/w:pict/v:shape', 'style')); + $this->assertStringMatchesFormat('%Sheight:200px%S', $doc->getElementAttribute($baseXpath . '[1]/w:pict/v:shape', 'style')); $this->assertStringMatchesFormat('%Smso-position-horizontal:right%S', $doc->getElementAttribute($baseXpath . '[1]/w:pict/v:shape', 'style')); $this->assertStringMatchesFormat('%Smso-position-horizontal:left%S', $doc->getElementAttribute($baseXpath . '[2]/w:pict/v:shape', 'style')); } From 47c837abef8f25fa0f28da352cd3e94c8be99ece Mon Sep 17 00:00:00 2001 From: troosan Date: Tue, 6 Feb 2018 23:31:56 +0100 Subject: [PATCH 016/135] add unit tests --- src/PhpWord/Shared/Html.php | 4 ---- tests/PhpWord/Shared/HtmlTest.php | 29 ++++++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 2eeaae8b5a..e11d7390f3 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -366,10 +366,6 @@ private static function parseCell($node, $element, &$styles) */ private static function shouldAddTextRun(\DOMNode $node) { - if (!$node->hasChildNodes()) { - return false; - } - $containsBlockElement = self::$xpath->query('.//table|./p', $node)->length > 0; if ($containsBlockElement) { return false; diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index 7d5f0b4c17..44fe97fc3e 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -150,6 +150,33 @@ public function testParseFontSize() $this->assertEquals('15', $doc->getElementAttribute('/w:document/w:body/w:p[2]/w:r/w:rPr/w:sz', 'w:val')); } + /** + * Test direction style + */ + public function testParseTextDirection() + { + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + Html::addHtml($section, 'test'); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:rPr/w:rtl')); + } + + /** + * Test html lang + */ + public function testParseLang() + { + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + Html::addHtml($section, 'test'); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:rPr/w:lang')); + $this->assertEquals('fr-BE', $doc->getElementAttribute('/w:document/w:body/w:p/w:r/w:rPr/w:lang', 'w:val')); + } + /** * Test font-family style */ @@ -199,7 +226,7 @@ public function testParseTable() 12 - 456 + This is bold text5

      6

      '; Html::addHtml($section, $html); From 46476d71014a1136810bdf7576724edc6e50fe30 Mon Sep 17 00:00:00 2001 From: troosan Date: Wed, 7 Feb 2018 07:09:27 +0100 Subject: [PATCH 017/135] update phpdoc --- src/PhpWord/Shared/Html.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index e11d7390f3..2a92ed2a72 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -339,7 +339,7 @@ private static function parseRow($node, $element, &$styles) * @param \DOMNode $node * @param \PhpOffice\PhpWord\Element\Table $element * @param array &$styles - * @return \PhpOffice\PhpWord\Element\Cell $element + * @return \PhpOffice\PhpWord\Element\Cell|\PhpOffice\PhpWord\Element\TextRun $element */ private static function parseCell($node, $element, &$styles) { From 33739ea21cbdc74b661ed8e9de42a75db7c6391e Mon Sep 17 00:00:00 2001 From: troosan Date: Wed, 7 Feb 2018 21:39:01 +0100 Subject: [PATCH 018/135] cannot add list on textrun --- src/PhpWord/Shared/Html.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 2a92ed2a72..a3ea0cc0fc 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -366,7 +366,7 @@ private static function parseCell($node, $element, &$styles) */ private static function shouldAddTextRun(\DOMNode $node) { - $containsBlockElement = self::$xpath->query('.//table|./p', $node)->length > 0; + $containsBlockElement = self::$xpath->query('.//table|./p|./ul|./li', $node)->length > 0; if ($containsBlockElement) { return false; } From 304173c4d78b65685e2e91654beccd573fe8b4ee Mon Sep 17 00:00:00 2001 From: troosan Date: Thu, 8 Feb 2018 07:02:28 +0100 Subject: [PATCH 019/135] fix nested list --- src/PhpWord/Element/AbstractElement.php | 13 +++++++++++++ src/PhpWord/Shared/Html.php | 7 +++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/PhpWord/Element/AbstractElement.php b/src/PhpWord/Element/AbstractElement.php index 63892b74ea..5227964542 100644 --- a/src/PhpWord/Element/AbstractElement.php +++ b/src/PhpWord/Element/AbstractElement.php @@ -93,6 +93,13 @@ abstract class AbstractElement */ private $nestedLevel = 0; + /** + * A reference to the parent + * + * @var \PhpOffice\PhpWord\Element\AbstractElement + */ + private $parent; + /** * Parent container type * @@ -321,6 +328,11 @@ public function setCommentRangeEnd(Comment $value) $this->commentRangeEnd->setEndElement($this); } + public function getParent() + { + return $this->parent; + } + /** * Set parent container * @@ -331,6 +343,7 @@ public function setCommentRangeEnd(Comment $value) public function setParentContainer(AbstractElement $container) { $this->parentContainer = substr(get_class($container), strrpos(get_class($container), '\\') + 1); + $this->parent = $container; // Set nested level $this->nestedLevel = $container->getNestedLevel(); diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index a3ea0cc0fc..971776ff93 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -366,7 +366,7 @@ private static function parseCell($node, $element, &$styles) */ private static function shouldAddTextRun(\DOMNode $node) { - $containsBlockElement = self::$xpath->query('.//table|./p|./ul|./li', $node)->length > 0; + $containsBlockElement = self::$xpath->query('.//table|./p|./ul|./ol', $node)->length > 0; if ($containsBlockElement) { return false; } @@ -402,7 +402,7 @@ private static function recursiveParseStylesInHierarchy(\DOMNode $node, array $s */ private static function parseList($node, $element, &$styles, &$data) { - $isOrderedList = $node->nodeName == 'ol'; + $isOrderedList = $node->nodeName === 'ol'; if (isset($data['listdepth'])) { $data['listdepth']++; } else { @@ -410,6 +410,9 @@ private static function parseList($node, $element, &$styles, &$data) $styles['list'] = 'listStyle_' . self::$listIndex++; $element->getPhpWord()->addNumberingStyle($styles['list'], self::getListStyle($isOrderedList)); } + if ($node->parentNode->nodeName === 'li') { + return $element->getParent(); + } } private static function getListStyle($isOrderedList) From 24f3463f9af8a4ade049d11202ee8e34bec92ec3 Mon Sep 17 00:00:00 2001 From: troosan Date: Thu, 8 Feb 2018 07:18:02 +0100 Subject: [PATCH 020/135] remove output --- CHANGELOG.md | 3 ++- tests/PhpWord/Shared/HtmlTest.php | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fca2922ce0..21f4ec81c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,11 +8,12 @@ v0.15.0 (?? ??? 2018) ### Added - Parsing of "align" HTML attribute - @troosan #1231 - Parse formatting inside HTML lists - @troosan @samimussbach #1239 #945 #1215 #508 -- Parsing of CSS `direction` instruction, HTML `lang` attribute, formatting inside table cell - @troosan # +- Parsing of CSS `direction` instruction, HTML `lang` attribute, formatting inside table cell - @troosan #1273 #1252 #1254 ### Fixed - fix reading of docx default style - @troosan #1238 - fix the size unit of when parsing html images - @troosan #1254 +- fixed HTML parsing of nested lists - @troosan #1265 diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index b1ebf3493d..ac68b8876c 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -323,7 +323,7 @@ public function testOrderedNestedListNumbering() Html::addHtml($section, $html, false, false); $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); - echo $doc->printXml(); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:pPr/w:numPr/w:numId')); $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:t')); From 9cd5ab74330f9957b99c7d4634bf95fdb7e1a9e6 Mon Sep 17 00:00:00 2001 From: troosan Date: Fri, 9 Feb 2018 17:17:13 +0100 Subject: [PATCH 021/135] update changelog --- CHANGELOG.md | 1 + samples/Sample_26_Html.php | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21f4ec81c7..3d3f60f3e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ v0.15.0 (?? ??? 2018) - fix reading of docx default style - @troosan #1238 - fix the size unit of when parsing html images - @troosan #1254 - fixed HTML parsing of nested lists - @troosan #1265 +- Save PNG alpha information when using remote images. @samsullivan #779 diff --git a/samples/Sample_26_Html.php b/samples/Sample_26_Html.php index 6e505fdb70..f608635792 100644 --- a/samples/Sample_26_Html.php +++ b/samples/Sample_26_Html.php @@ -37,7 +37,6 @@
    3. sub list 2
    -
  7. List 2 item 3
    1. sub list 1, restarts with a
    2. From 604e60cae9cad0e5d114ddda0c88c6e2ebe93693 Mon Sep 17 00:00:00 2001 From: troosan Date: Fri, 9 Feb 2018 21:49:11 +0100 Subject: [PATCH 022/135] Add support for Track changes (#1262) * add changed information to HTML writer * add missing writeFontStyle * refactor track changes * set the style * update documentation and release note * Update the changelog and doc * fix scrutinizer issues --- CHANGELOG.md | 1 + docs/elements.rst | 41 +++++++++-- samples/Sample_16_Object.php | 2 +- samples/Sample_39_TrackChanges.php | 29 ++++++++ samples/resources/Sample_11_ReadWord2007.docx | Bin 67881 -> 63320 bytes samples/resources/Sample_24_ReadODText.odt | Bin 11952 -> 11540 bytes src/PhpWord/Element/AbstractContainer.php | 4 +- src/PhpWord/Element/AbstractElement.php | 39 +++++++++++ src/PhpWord/Element/Comment.php | 4 +- src/PhpWord/Element/TrackChange.php | 31 ++++++++- src/PhpWord/Reader/ODText/Content.php | 50 +++++++++++++- src/PhpWord/Reader/Word2007/AbstractPart.php | 27 +++++++- src/PhpWord/Reader/Word2007/Styles.php | 2 +- src/PhpWord/Writer/HTML/Element/Text.php | 65 ++++++++++++++++++ src/PhpWord/Writer/ODText/Element/Text.php | 58 +++++++++++----- src/PhpWord/Writer/ODText/Part/Content.php | 55 +++++++++++++++ src/PhpWord/Writer/Word2007/Element/Text.php | 54 ++++++++++++++- tests/PhpWord/Element/TrackChangeTest.php | 44 ++++++++++++ tests/PhpWord/Shared/HtmlTest.php | 2 +- tests/PhpWord/Writer/Word2007/ElementTest.php | 18 ++++- 20 files changed, 487 insertions(+), 39 deletions(-) create mode 100644 samples/Sample_39_TrackChanges.php create mode 100644 tests/PhpWord/Element/TrackChangeTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index d6f8b2da00..f82759dc10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ v0.15.0 (?? ??? 2018) ### Added - Parsing of "align" HTML attribute - @troosan #1231 - Parse formatting inside HTML lists - @troosan @samimussbach #1239 #945 #1215 #508 +- Add support for Track changes @Cip @troosan #354 #1262 ### Fixed - fix reading of docx default style - @troosan #1238 diff --git a/docs/elements.rst b/docs/elements.rst index fe67330489..7df3b16359 100644 --- a/docs/elements.rst +++ b/docs/elements.rst @@ -31,7 +31,7 @@ column shows the containers while the rows lists the elements. +-------+-----------------+-----------+----------+----------+---------+------------+------------+ | 11 | Watermark | - | v | - | - | - | - | +-------+-----------------+-----------+----------+----------+---------+------------+------------+ -| 12 | Object | v | v | v | v | v | v | +| 12 | OLEObject | v | v | v | v | v | v | +-------+-----------------+-----------+----------+----------+---------+------------+------------+ | 13 | TOC | v | - | - | - | - | - | +-------+-----------------+-----------+----------+----------+---------+------------+------------+ @@ -77,6 +77,13 @@ italics, etc) or other elements, e.g. images or links. The syntaxes are as follo For available styling options see :ref:`font-style` and :ref:`paragraph-style`. +If you want to enable track changes on added text you can mark it as INSERTED or DELETED by a specific user at a given time: + +.. code-block:: php + + $text = $section->addText('Hello World!'); + $text->setChanged(\PhpOffice\PhpWord\Element\ChangedElement::TYPE_INSERTED, 'Fred', (new \DateTime())); + Titles ~~~~~~ @@ -276,11 +283,11 @@ Objects ------- You can add OLE embeddings, such as Excel spreadsheets or PowerPoint -presentations to the document by using ``addObject`` method. +presentations to the document by using ``addOLEObject`` method. .. code-block:: php - $section->addObject($src, [$style]); + $section->addOLEObject($src, [$style]); Table of contents ----------------- @@ -309,7 +316,7 @@ Footnotes & endnotes You can create footnotes with ``addFootnote`` and endnotes with ``addEndnote`` in texts or textruns, but it's recommended to use textrun to have better layout. You can use ``addText``, ``addLink``, -``addTextBreak``, ``addImage``, ``addObject`` on footnotes and endnotes. +``addTextBreak``, ``addImage``, ``addOLEObject`` on footnotes and endnotes. On textrun: @@ -465,4 +472,28 @@ The comment can contain formatted text. Once the comment has been added, it can // link the comment to the text you just created $text->setCommentStart($comment); -If no end is set for a comment using the ``setCommentEnd``, the comment will be ended automatically at the end of the element it is started on. \ No newline at end of file +If no end is set for a comment using the ``setCommentEnd``, the comment will be ended automatically at the end of the element it is started on. + +Track Changes +------------- + +Track changes can be set on text elements. There are 2 ways to set the change information on an element. +Either by calling the `setChangeInfo()`, or by setting the `TrackChange` instance on the element with `setTrackChange()`. + +.. code-block:: php + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + + // New portrait section + $section = $phpWord->addSection(); + $textRun = $section->addTextRun(); + + $text = $textRun->addText('Hello World! Time to '); + + $text = $textRun->addText('wake ', array('bold' => true)); + $text->setChangeInfo(TrackChange::INSERTED, 'Fred', time() - 1800); + + $text = $textRun->addText('up'); + $text->setTrackChange(new TrackChange(TrackChange::INSERTED, 'Fred')); + + $text = $textRun->addText('go to sleep'); + $text->setChangeInfo(TrackChange::DELETED, 'Barney', new \DateTime('@' . (time() - 3600))); diff --git a/samples/Sample_16_Object.php b/samples/Sample_16_Object.php index 8b05b9e8ac..c4db7f6106 100644 --- a/samples/Sample_16_Object.php +++ b/samples/Sample_16_Object.php @@ -9,7 +9,7 @@ $section = $phpWord->addSection(); $section->addText('You can open this OLE object by double clicking on the icon:'); $section->addTextBreak(2); -$section->addObject('resources/_sheet.xls'); +$section->addOLEObject('resources/_sheet.xls'); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/samples/Sample_39_TrackChanges.php b/samples/Sample_39_TrackChanges.php new file mode 100644 index 0000000000..e6a3066864 --- /dev/null +++ b/samples/Sample_39_TrackChanges.php @@ -0,0 +1,29 @@ +addSection(); +$textRun = $section->addTextRun(); + +$text = $textRun->addText('Hello World! Time to '); + +$text = $textRun->addText('wake ', array('bold' => true)); +$text->setChangeInfo(TrackChange::INSERTED, 'Fred', time() - 1800); + +$text = $textRun->addText('up'); +$text->setTrackChange(new TrackChange(TrackChange::INSERTED, 'Fred')); + +$text = $textRun->addText('go to sleep'); +$text->setChangeInfo(TrackChange::DELETED, 'Barney', new \DateTime('@' . (time() - 3600))); + +// Save file +echo write($phpWord, basename(__FILE__, '.php'), $writers); +if (!CLI) { + include_once 'Sample_Footer.php'; +} diff --git a/samples/resources/Sample_11_ReadWord2007.docx b/samples/resources/Sample_11_ReadWord2007.docx index c9a50f485a3c8d942fc7982061c5905f342c7634..3faf6f1213f13e82466ef29200862498d2ef7014 100644 GIT binary patch delta 52080 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

      g(bZr8|pUC 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 P4(J~eD8+I5jWl8rRIjFz2 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

      m|{ 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 HOYQ#wPQ_E} literal 11952 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 = $trackChange; + } + + /** + * Gets the trackChange information + * + * @return TrackChange + */ + public function getTrackChange() + { + return $this->trackChange; + } + + /** + * Set changed + * + * @param string $type INSERTED|DELETED + * @param string $author + * @param null|int|\DateTime $date allways in UTC + */ + public function setChangeInfo($type, $author, $date = null) + { + $this->trackChange = new TrackChange($type, $author, $date); + } + /** * Set enum value * diff --git a/src/PhpWord/Element/Comment.php b/src/PhpWord/Element/Comment.php index 188369292c..205ff598b9 100644 --- a/src/PhpWord/Element/Comment.php +++ b/src/PhpWord/Element/Comment.php @@ -55,12 +55,12 @@ class Comment extends TrackChange * Create a new Comment Element * * @param string $author - * @param \DateTime $date + * @param null|\DateTime $date * @param string $initials */ public function __construct($author, $date = null, $initials = null) { - parent::__construct($author, $date); + parent::__construct(null, $author, $date); $this->initials = $initials; } diff --git a/src/PhpWord/Element/TrackChange.php b/src/PhpWord/Element/TrackChange.php index 44327f263f..dde616cc21 100644 --- a/src/PhpWord/Element/TrackChange.php +++ b/src/PhpWord/Element/TrackChange.php @@ -20,14 +20,25 @@ /** * TrackChange element * @see http://datypic.com/sc/ooxml/t-w_CT_TrackChange.html + * @see http://datypic.com/sc/ooxml/t-w_CT_RunTrackChange.html */ class TrackChange extends AbstractContainer { + const INSERTED = 'INSERTED'; + const DELETED = 'DELETED'; + /** * @var string Container type */ protected $container = 'TrackChange'; + /** + * The type of change, (insert or delete), not applicable for PhpOffice\PhpWord\Element\Comment + * + * @var string + */ + private $changeType; + /** * Author * @@ -45,13 +56,17 @@ class TrackChange extends AbstractContainer /** * Create a new TrackChange Element * + * @param string $changeType * @param string $author - * @param \DateTime $date + * @param null|int|\DateTime $date */ - public function __construct($author, \DateTime $date = null) + public function __construct($changeType = null, $author = null, $date = null) { + $this->changeType = $changeType; $this->author = $author; - $this->date = $date; + if ($date !== null) { + $this->date = ($date instanceof \DateTime) ? $date : new \DateTime('@' . $date); + } } /** @@ -73,4 +88,14 @@ public function getDate() { return $this->date; } + + /** + * Get the Change type + * + * @return string + */ + public function getChangeType() + { + return $this->changeType; + } } diff --git a/src/PhpWord/Reader/ODText/Content.php b/src/PhpWord/Reader/ODText/Content.php index 8843d8a276..7a7a046837 100644 --- a/src/PhpWord/Reader/ODText/Content.php +++ b/src/PhpWord/Reader/ODText/Content.php @@ -18,6 +18,7 @@ namespace PhpOffice\PhpWord\Reader\ODText; use PhpOffice\Common\XMLReader; +use PhpOffice\PhpWord\Element\TrackChange; use PhpOffice\PhpWord\PhpWord; /** @@ -37,6 +38,8 @@ public function read(PhpWord $phpWord) $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($this->docFile, $this->xmlFile); + $trackedChanges = array(); + $nodes = $xmlReader->getElements('office:body/office:text/*'); if ($nodes->length > 0) { $section = $phpWord->addSection(); @@ -48,7 +51,37 @@ public function read(PhpWord $phpWord) $section->addTitle($node->nodeValue, $depth); break; case 'text:p': // Paragraph - $section->addText($node->nodeValue); + $children = $node->childNodes; + foreach ($children as $child) { + switch ($child->nodeName) { + case 'text:change-start': + $changeId = $child->getAttribute('text:change-id'); + if (isset($trackedChanges[$changeId])) { + $changed = $trackedChanges[$changeId]; + } + break; + case 'text:change-end': + unset($changed); + break; + case 'text:change': + $changeId = $child->getAttribute('text:change-id'); + if (isset($trackedChanges[$changeId])) { + $changed = $trackedChanges[$changeId]; + } + break; + } + } + + $element = $section->addText($node->nodeValue); + if (isset($changed) && is_array($changed)) { + $element->setTrackChange($changed['changed']); + if (isset($changed['textNodes'])) { + foreach ($changed['textNodes'] as $changedNode) { + $element = $section->addText($changedNode->nodeValue); + $element->setTrackChange($changed['changed']); + } + } + } break; case 'text:list': // List $listItems = $xmlReader->getElements('text:list-item/text:p', $node); @@ -57,6 +90,21 @@ public function read(PhpWord $phpWord) $section->addListItem($listItem->nodeValue, 0); } break; + case 'text:tracked-changes': + $changedRegions = $xmlReader->getElements('text:changed-region', $node); + foreach ($changedRegions as $changedRegion) { + $type = ($changedRegion->firstChild->nodeName == 'text:insertion') ? TrackChange::INSERTED : TrackChange::DELETED; + $creatorNode = $xmlReader->getElements('office:change-info/dc:creator', $changedRegion->firstChild); + $author = $creatorNode[0]->nodeValue; + $dateNode = $xmlReader->getElements('office:change-info/dc:date', $changedRegion->firstChild); + $date = $dateNode[0]->nodeValue; + $date = preg_replace('/\.\d+$/', '', $date); + $date = \DateTime::createFromFormat('Y-m-d\TH:i:s', $date); + $changed = new TrackChange($type, $author, $date); + $textNodes = $xmlReader->getElements('text:deletion/text:p', $changedRegion); + $trackedChanges[$changedRegion->getAttribute('text:id')] = array('changed' => $changed, 'textNodes'=> $textNodes); + } + break; } } } diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 3d853e8f24..366bde7e24 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -18,6 +18,7 @@ namespace PhpOffice\PhpWord\Reader\Word2007; use PhpOffice\Common\XMLReader; +use PhpOffice\PhpWord\Element\TrackChange; use PhpOffice\PhpWord\PhpWord; /** @@ -156,8 +157,10 @@ protected function readParagraph(XMLReader $xmlReader, \DOMElement $domNode, $pa } else { // Text and TextRun $runCount = $xmlReader->countElements('w:r', $domNode); + $insCount = $xmlReader->countElements('w:ins', $domNode); + $delCount = $xmlReader->countElements('w:del', $domNode); $linkCount = $xmlReader->countElements('w:hyperlink', $domNode); - $runLinkCount = $runCount + $linkCount; + $runLinkCount = $runCount + $insCount + $delCount + $linkCount; if (0 == $runLinkCount) { $parent->addTextBreak(null, $paragraphStyle); } else { @@ -185,6 +188,13 @@ protected function readParagraph(XMLReader $xmlReader, \DOMElement $domNode, $pa */ protected function readRun(XMLReader $xmlReader, \DOMElement $domNode, $parent, $docPart, $paragraphStyle = null) { + if (in_array($domNode->nodeName, array('w:ins', 'w:del'))) { + $nodes = $xmlReader->getElements('*', $domNode); + foreach ($nodes as $node) { + return $this->readRun($xmlReader, $node, $parent, $docPart, $paragraphStyle); + } + } + if (!in_array($domNode->nodeName, array('w:r', 'w:hyperlink'))) { return; } @@ -228,8 +238,19 @@ protected function readRun(XMLReader $xmlReader, \DOMElement $domNode, $parent, } } else { // TextRun - $textContent = $xmlReader->getValue('w:t', $domNode); - $parent->addText($textContent, $fontStyle, $paragraphStyle); + if ($domNode->parentNode->nodeName == 'w:del') { + $textContent = $xmlReader->getValue('w:delText', $domNode); + } else { + $textContent = $xmlReader->getValue('w:t', $domNode); + } + /** @var AbstractElement $element */ + $element = $parent->addText($textContent, $fontStyle, $paragraphStyle); + if (in_array($domNode->parentNode->nodeName, array('w:ins', 'w:del'))) { + $type = ($domNode->parentNode->nodeName == 'w:del') ? TrackChange::DELETED : TrackChange::INSERTED; + $author = $domNode->parentNode->getAttribute('w:author'); + $date = \DateTime::createFromFormat('Y-m-d\TH:i:s\Z', $domNode->parentNode->getAttribute('w:date')); + $element->setChangeInfo($type, $author, $date); + } } } } diff --git a/src/PhpWord/Reader/Word2007/Styles.php b/src/PhpWord/Reader/Word2007/Styles.php index c6e64e45f5..8719641ec2 100644 --- a/src/PhpWord/Reader/Word2007/Styles.php +++ b/src/PhpWord/Reader/Word2007/Styles.php @@ -56,7 +56,7 @@ public function read(PhpWord $phpWord) if ($paragraphDefaults !== null) { $paragraphDefaultStyle = $this->readParagraphStyle($xmlReader, $paragraphDefaults); if ($paragraphDefaultStyle != null) { - $phpWord->setDefaultParagraphStyle(); + $phpWord->setDefaultParagraphStyle($paragraphDefaultStyle); } } diff --git a/src/PhpWord/Writer/HTML/Element/Text.php b/src/PhpWord/Writer/HTML/Element/Text.php index 71cb75669a..9f8f7773c5 100644 --- a/src/PhpWord/Writer/HTML/Element/Text.php +++ b/src/PhpWord/Writer/HTML/Element/Text.php @@ -17,6 +17,7 @@ namespace PhpOffice\PhpWord\Writer\HTML\Element; +use PhpOffice\PhpWord\Element\TrackChange; use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Style\Font; use PhpOffice\PhpWord\Style\Paragraph; @@ -121,6 +122,9 @@ protected function writeOpening() $content .= ""; } + //open track change tag + $content .= $this->writeTrackChangeOpening(); + return $content; } @@ -132,6 +136,10 @@ protected function writeOpening() protected function writeClosing() { $content = ''; + + //close track change tag + $content .= $this->writeTrackChangeClosing(); + if (!$this->withoutP) { if (Settings::isOutputEscapingEnabled()) { $content .= $this->escaper->escapeHtml($this->closingText); @@ -145,6 +153,63 @@ protected function writeClosing() return $content; } + /** + * writes the track change opening tag + * + * @return string the HTML, an empty string if no track change information + */ + private function writeTrackChangeOpening() + { + $changed = $this->element->getTrackChange(); + if ($changed == null) { + return ''; + } + + $content = ''; + if (($changed->getChangeType() == TrackChange::INSERTED)) { + $content .= 'getChangeType() == TrackChange::DELETED) { + $content .= ' array('author'=> $changed->getAuthor(), 'id' => $this->element->getElementId())); + if ($changed->getDate() != null) { + $changedProp['changed']['date'] = $changed->getDate()->format('Y-m-d\TH:i:s\Z'); + } + $content .= json_encode($changedProp); + $content .= '\' '; + $content .= 'title="' . $changed->getAuthor(); + if ($changed->getDate() != null) { + $dateUser = $changed->getDate()->format('Y-m-d H:i:s'); + $content .= ' - ' . $dateUser; + } + $content .= '">'; + + return $content; + } + + /** + * writes the track change closing tag + * + * @return string the HTML, an empty string if no track change information + */ + private function writeTrackChangeClosing() + { + $changed = $this->element->getTrackChange(); + if ($changed == null) { + return ''; + } + + $content = ''; + if (($changed->getChangeType() == TrackChange::INSERTED)) { + $content .= ''; + } elseif ($changed->getChangeType() == TrackChange::DELETED) { + $content .= ''; + } + + return $content; + } + /** * Write paragraph style * diff --git a/src/PhpWord/Writer/ODText/Element/Text.php b/src/PhpWord/Writer/ODText/Element/Text.php index 1fc0b80028..f9259fc501 100644 --- a/src/PhpWord/Writer/ODText/Element/Text.php +++ b/src/PhpWord/Writer/ODText/Element/Text.php @@ -17,6 +17,7 @@ namespace PhpOffice\PhpWord\Writer\ODText\Element; +use PhpOffice\PhpWord\Element\TrackChange; use PhpOffice\PhpWord\Exception\Exception; /** @@ -51,29 +52,50 @@ public function write() if (!$this->withoutP) { $xmlWriter->startElement('text:p'); // text:p } - if (empty($fontStyle)) { - if (empty($paragraphStyle)) { - $xmlWriter->writeAttribute('text:style-name', 'P1'); - } elseif (is_string($paragraphStyle)) { - $xmlWriter->writeAttribute('text:style-name', $paragraphStyle); - } - $this->writeText($element->getText()); + if ($element->getTrackChange() != null && $element->getTrackChange()->getChangeType() == TrackChange::DELETED) { + $xmlWriter->startElement('text:change'); + $xmlWriter->writeAttribute('text:change-id', $element->getTrackChange()->getElementId()); + $xmlWriter->endElement(); } else { - if (empty($paragraphStyle)) { - $xmlWriter->writeAttribute('text:style-name', 'Standard'); - } elseif (is_string($paragraphStyle)) { - $xmlWriter->writeAttribute('text:style-name', $paragraphStyle); - } - // text:span - $xmlWriter->startElement('text:span'); - if (is_string($fontStyle)) { - $xmlWriter->writeAttribute('text:style-name', $fontStyle); + if (empty($fontStyle)) { + if (empty($paragraphStyle)) { + $xmlWriter->writeAttribute('text:style-name', 'P1'); + } elseif (is_string($paragraphStyle)) { + $xmlWriter->writeAttribute('text:style-name', $paragraphStyle); + } + $this->writeChangeInsertion(true, $element->getTrackChange()); + $this->writeText($element->getText()); + $this->writeChangeInsertion(false, $element->getTrackChange()); + } else { + if (empty($paragraphStyle)) { + $xmlWriter->writeAttribute('text:style-name', 'Standard'); + } elseif (is_string($paragraphStyle)) { + $xmlWriter->writeAttribute('text:style-name', $paragraphStyle); + } + // text:span + $xmlWriter->startElement('text:span'); + if (is_string($fontStyle)) { + $xmlWriter->writeAttribute('text:style-name', $fontStyle); + } + $this->writeChangeInsertion(true, $element->getTrackChange()); + $this->writeText($element->getText()); + $this->writeChangeInsertion(false, $element->getTrackChange()); + $xmlWriter->endElement(); } - $this->writeText($element->getText()); - $xmlWriter->endElement(); } if (!$this->withoutP) { $xmlWriter->endElement(); // text:p } } + + private function writeChangeInsertion($start = true, TrackChange $trackChange = null) + { + if ($trackChange == null || $trackChange->getChangeType() != TrackChange::INSERTED) { + return; + } + $xmlWriter = $this->getXmlWriter(); + $xmlWriter->startElement('text:change-' . ($start ? 'start' : 'end')); + $xmlWriter->writeAttribute('text:change-id', $trackChange->getElementId()); + $xmlWriter->endElement(); + } } diff --git a/src/PhpWord/Writer/ODText/Part/Content.php b/src/PhpWord/Writer/ODText/Part/Content.php index 8ae4dca9c7..19d3e54ab0 100644 --- a/src/PhpWord/Writer/ODText/Part/Content.php +++ b/src/PhpWord/Writer/ODText/Part/Content.php @@ -18,10 +18,12 @@ namespace PhpOffice\PhpWord\Writer\ODText\Part; use PhpOffice\Common\XMLWriter; +use PhpOffice\PhpWord\Element\AbstractContainer; use PhpOffice\PhpWord\Element\Image; use PhpOffice\PhpWord\Element\Table; use PhpOffice\PhpWord\Element\Text; use PhpOffice\PhpWord\Element\TextRun; +use PhpOffice\PhpWord\Element\TrackChange; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Style; use PhpOffice\PhpWord\Style\Font; @@ -74,6 +76,40 @@ public function write() $xmlWriter->startElement('office:body'); $xmlWriter->startElement('office:text'); + // Tracked changes declarations + $trackedChanges = array(); + $sections = $phpWord->getSections(); + foreach ($sections as $section) { + $this->collectTrackedChanges($section, $trackedChanges); + } + $xmlWriter->startElement('text:tracked-changes'); + foreach ($trackedChanges as $trackedElement) { + $trackedChange = $trackedElement->getTrackChange(); + $xmlWriter->startElement('text:changed-region'); + $trackedChange->setElementId(); + $xmlWriter->writeAttribute('text:id', $trackedChange->getElementId()); + + if (($trackedChange->getChangeType() == TrackChange::INSERTED)) { + $xmlWriter->startElement('text:insertion'); + } elseif ($trackedChange->getChangeType() == TrackChange::DELETED) { + $xmlWriter->startElement('text:deletion'); + } + + $xmlWriter->startElement('office:change-info'); + $xmlWriter->writeElement('dc:creator', $trackedChange->getAuthor()); + if ($trackedChange->getDate() != null) { + $xmlWriter->writeElement('dc:date', $trackedChange->getDate()->format('Y-m-d\TH:i:s\Z')); + } + $xmlWriter->endElement(); // office:change-info + if ($trackedChange->getChangeType() == TrackChange::DELETED) { + $xmlWriter->writeElement('text:p', $trackedElement->getText()); + } + + $xmlWriter->endElement(); // text:insertion|text:deletion + $xmlWriter->endElement(); // text:changed-region + } + $xmlWriter->endElement(); // text:tracked-changes + // Sequence declarations $sequences = array('Illustration', 'Table', 'Text', 'Drawing'); $xmlWriter->startElement('text:sequence-decls'); @@ -242,4 +278,23 @@ private function getElementStyle(&$element, &$paragraphStyleCount, &$fontStyleCo $element->setParagraphStyle("P{$paragraphStyleCount}"); } } + + /** + * Finds all tracked changes + * + * @param AbstractContainer $container + * @param \PhpOffice\PhpWord\Element\AbstractElement[] $trackedChanges + */ + private function collectTrackedChanges(AbstractContainer $container, &$trackedChanges = array()) + { + $elements = $container->getElements(); + foreach ($elements as $element) { + if ($element->getTrackChange() != null) { + $trackedChanges[] = $element; + } + if (is_callable(array($element, 'getElements'))) { + $this->collectTrackedChanges($element, $trackedChanges); + } + } + } } diff --git a/src/PhpWord/Writer/Word2007/Element/Text.php b/src/PhpWord/Writer/Word2007/Element/Text.php index e714943222..130b912bad 100644 --- a/src/PhpWord/Writer/Word2007/Element/Text.php +++ b/src/PhpWord/Writer/Word2007/Element/Text.php @@ -17,6 +17,8 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Element; +use PhpOffice\PhpWord\Element\TrackChange; + /** * Text element writer * @@ -37,16 +39,66 @@ public function write() $this->startElementP(); + $this->writeOpeningTrackChange(); + $xmlWriter->startElement('w:r'); $this->writeFontStyle(); - $xmlWriter->startElement('w:t'); + $textElement = 'w:t'; + //'w:delText' in case of deleted text + $changed = $element->getTrackChange(); + if ($changed != null && $changed->getChangeType() == TrackChange::DELETED) { + $textElement = 'w:delText'; + } + $xmlWriter->startElement($textElement); + $xmlWriter->writeAttribute('xml:space', 'preserve'); $this->writeText($this->getText($element->getText())); $xmlWriter->endElement(); $xmlWriter->endElement(); // w:r + $this->writeClosingTrackChange(); + $this->endElementP(); // w:p } + + /** + * Write opening of changed element + */ + protected function writeOpeningTrackChange() + { + $changed = $this->getElement()->getTrackChange(); + if ($changed == null) { + return; + } + + $xmlWriter = $this->getXmlWriter(); + + if (($changed->getChangeType() == TrackChange::INSERTED)) { + $xmlWriter->startElement('w:ins'); + } elseif ($changed->getChangeType() == TrackChange::DELETED) { + $xmlWriter->startElement('w:del'); + } + $xmlWriter->writeAttribute('w:author', $changed->getAuthor()); + if ($changed->getDate() != null) { + $xmlWriter->writeAttribute('w:date', $changed->getDate()->format('Y-m-d\TH:i:s\Z')); + } + $xmlWriter->writeAttribute('w:id', $this->getElement()->getElementId()); + } + + /** + * Write ending + */ + protected function writeClosingTrackChange() + { + $changed = $this->getElement()->getTrackChange(); + if ($changed == null) { + return; + } + + $xmlWriter = $this->getXmlWriter(); + + $xmlWriter->endElement(); // w:ins|w:del + } } diff --git a/tests/PhpWord/Element/TrackChangeTest.php b/tests/PhpWord/Element/TrackChangeTest.php new file mode 100644 index 0000000000..3249f10be3 --- /dev/null +++ b/tests/PhpWord/Element/TrackChangeTest.php @@ -0,0 +1,44 @@ +setTrackChange($oTrackChange); + + $this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\TrackChange', $oTrackChange); + $this->assertEquals($author, $oTrackChange->getAuthor()); + $this->assertEquals($date, $oTrackChange->getDate()); + $this->assertEquals(TrackChange::INSERTED, $oTrackChange->getChangeType()); + } +} diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index 97a8fb156f..1ad2ff5394 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -259,7 +259,7 @@ public function testOrderedListNumbering() Html::addHtml($section, $html, false, false); $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); - echo $doc->printXml(); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:pPr/w:numPr/w:numId')); $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:t')); diff --git a/tests/PhpWord/Writer/Word2007/ElementTest.php b/tests/PhpWord/Writer/Word2007/ElementTest.php index 4f0d50d96a..f91a8479da 100644 --- a/tests/PhpWord/Writer/Word2007/ElementTest.php +++ b/tests/PhpWord/Writer/Word2007/ElementTest.php @@ -19,8 +19,8 @@ use PhpOffice\Common\XMLWriter; use PhpOffice\PhpWord\Element\Comment; -use PhpOffice\PhpWord\Element\Text; use PhpOffice\PhpWord\Element\TextRun; +use PhpOffice\PhpWord\Element\TrackChange; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\TestHelperDOCX; @@ -415,4 +415,20 @@ public function testCommentWithEndElement() $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:commentRangeEnd')); $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:commentReference')); } + + public function testTrackChange() + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $text = $section->addText('my dummy text'); + $text->setChangeInfo(TrackChange::INSERTED, 'author name'); + $text2 = $section->addText('my other text'); + $text2->setTrackChange(new TrackChange(TrackChange::DELETED, 'another author', new \DateTime())); + + $doc = TestHelperDOCX::getDocument($phpWord); + + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:ins/w:r')); + $this->assertEquals('author name', $doc->getElementAttribute('/w:document/w:body/w:p/w:ins', 'w:author')); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:del/w:r/w:delText')); + } } From 91a8dd3b221e24b9654c38576119b804f8f66634 Mon Sep 17 00:00:00 2001 From: troosan Date: Sat, 10 Feb 2018 22:16:55 +0100 Subject: [PATCH 023/135] add parsing of p:br and add unit test --- src/PhpWord/Reader/Word2007/AbstractPart.php | 10 +++- tests/PhpWord/Reader/Word2007/ElementTest.php | 46 +++++++++++++++ .../PhpWord/_includes/AbstractTestReader.php | 59 +++++++++++++++++++ 3 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 tests/PhpWord/Reader/Word2007/ElementTest.php create mode 100644 tests/PhpWord/_includes/AbstractTestReader.php diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 3d853e8f24..5ce84650bf 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -93,7 +93,7 @@ public function setRels($value) * * @param \PhpOffice\Common\XMLReader $xmlReader * @param \DOMElement $domNode - * @param mixed $parent + * @param \PhpOffice\PhpWord\Element\AbstractContainer $parent * @param string $docPart * * @todo Get font style for preserve text @@ -177,7 +177,7 @@ protected function readParagraph(XMLReader $xmlReader, \DOMElement $domNode, $pa * * @param \PhpOffice\Common\XMLReader $xmlReader * @param \DOMElement $domNode - * @param mixed $parent + * @param \PhpOffice\PhpWord\Element\AbstractContainer $parent * @param string $docPart * @param mixed $paragraphStyle * @@ -226,7 +226,11 @@ protected function readRun(XMLReader $xmlReader, \DOMElement $domNode, $parent, $textContent = "<Object: {$target}>"; $parent->addText($textContent, $fontStyle, $paragraphStyle); } - } else { + } + if ($xmlReader->elementExists('w:br', $domNode)) { + $parent->addTextBreak(); + } + if ($xmlReader->elementExists('w:t', $domNode)) { // TextRun $textContent = $xmlReader->getValue('w:t', $domNode); $parent->addText($textContent, $fontStyle, $paragraphStyle); diff --git a/tests/PhpWord/Reader/Word2007/ElementTest.php b/tests/PhpWord/Reader/Word2007/ElementTest.php new file mode 100644 index 0000000000..67c2eb1385 --- /dev/null +++ b/tests/PhpWord/Reader/Word2007/ElementTest.php @@ -0,0 +1,46 @@ + + + + test string + + '; + + $phpWord = $this->getDocumentFromString($documentXml); + + $elements = $this->get($phpWord->getSections(), 0)->getElements(); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\TextBreak', $elements[0]); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $elements[1]); + $this->assertEquals('test string', $elements[1]->getText()); + } +} diff --git a/tests/PhpWord/_includes/AbstractTestReader.php b/tests/PhpWord/_includes/AbstractTestReader.php new file mode 100644 index 0000000000..f138ac76d0 --- /dev/null +++ b/tests/PhpWord/_includes/AbstractTestReader.php @@ -0,0 +1,59 @@ +open($file, \ZipArchive::CREATE); + $zip->addFromString('document.xml', '' . $documentXml . ''); + $zip->close(); + $documentReader = new Document($file, 'document.xml'); + $documentReader->read($phpWord); + unlink($file); + + return $phpWord; + } + + /** + * Returns the element at position $index in the array + * + * @param array $array + * @param number $index + * @return mixed + */ + protected function get(array $array, $index = 0) + { + return $array[$index]; + } +} From 874c6d6fb6083ec2902e27d4e639f0b08aa3c76d Mon Sep 17 00:00:00 2001 From: troosan Date: Sat, 10 Feb 2018 22:19:04 +0100 Subject: [PATCH 024/135] update changelog --- CHANGELOG.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d3f60f3e8..ae661e5b5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,10 +11,11 @@ v0.15.0 (?? ??? 2018) - Parsing of CSS `direction` instruction, HTML `lang` attribute, formatting inside table cell - @troosan #1273 #1252 #1254 ### Fixed -- fix reading of docx default style - @troosan #1238 -- fix the size unit of when parsing html images - @troosan #1254 -- fixed HTML parsing of nested lists - @troosan #1265 +- Fix reading of docx default style - @troosan #1238 +- Fix the size unit of when parsing html images - @troosan #1254 +- Fixed HTML parsing of nested lists - @troosan #1265 - Save PNG alpha information when using remote images. @samsullivan #779 +- fix parsing of `` tag. @troosan #1274 From 377fb99fbc85683e2efcaf4e153a76b9cd558fe7 Mon Sep 17 00:00:00 2001 From: troosan Date: Sat, 10 Feb 2018 23:43:15 +0100 Subject: [PATCH 025/135] Add HTML writer for Bookmarks + tests --- CHANGELOG.md | 3 +- src/PhpWord/Writer/HTML/Element/Bookmark.php | 45 ++++++++++++++++++++ src/PhpWord/Writer/HTML/Element/Link.php | 8 ++-- tests/PhpWord/Writer/HTML/ElementTest.php | 2 +- tests/PhpWord/Writer/HTMLTest.php | 2 + 5 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 src/PhpWord/Writer/HTML/Element/Bookmark.php diff --git a/CHANGELOG.md b/CHANGELOG.md index ae661e5b5c..3b0110b91e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,8 @@ v0.15.0 (?? ??? 2018) - Fix the size unit of when parsing html images - @troosan #1254 - Fixed HTML parsing of nested lists - @troosan #1265 - Save PNG alpha information when using remote images. @samsullivan #779 -- fix parsing of `` tag. @troosan #1274 +- Fix parsing of `` tag. @troosan #1274 +- Bookmark are not writton as internal link in html writer @troosan #1263 diff --git a/src/PhpWord/Writer/HTML/Element/Bookmark.php b/src/PhpWord/Writer/HTML/Element/Bookmark.php new file mode 100644 index 0000000000..649cc7b86c --- /dev/null +++ b/src/PhpWord/Writer/HTML/Element/Bookmark.php @@ -0,0 +1,45 @@ +element instanceof \PhpOffice\PhpWord\Element\Bookmark) { + return ''; + } + + $content = ''; + $content .= $this->writeOpening(); + $content .= "element->getName()}\"/>"; + $content .= $this->writeClosing(); + + return $content; + } +} diff --git a/src/PhpWord/Writer/HTML/Element/Link.php b/src/PhpWord/Writer/HTML/Element/Link.php index bdea985a18..f29880d4c9 100644 --- a/src/PhpWord/Writer/HTML/Element/Link.php +++ b/src/PhpWord/Writer/HTML/Element/Link.php @@ -37,12 +37,12 @@ public function write() return ''; } - $content = ''; - $content .= $this->writeOpening(); + $prefix = $this->element->isInternal() ? '#' : ''; + $content = $this->writeOpening(); if (Settings::isOutputEscapingEnabled()) { - $content .= "escaper->escapeHtmlAttr($this->element->getSource())}\">{$this->escaper->escapeHtml($this->element->getText())}"; + $content .= "escaper->escapeHtmlAttr($this->element->getSource())}\">{$this->escaper->escapeHtml($this->element->getText())}"; } else { - $content .= "element->getSource()}\">{$this->element->getText()}"; + $content .= "element->getSource()}\">{$this->element->getText()}"; } $content .= $this->writeClosing(); diff --git a/tests/PhpWord/Writer/HTML/ElementTest.php b/tests/PhpWord/Writer/HTML/ElementTest.php index 86856d5c88..fc092ba313 100644 --- a/tests/PhpWord/Writer/HTML/ElementTest.php +++ b/tests/PhpWord/Writer/HTML/ElementTest.php @@ -31,7 +31,7 @@ class ElementTest extends \PHPUnit\Framework\TestCase */ public function testUnmatchedElements() { - $elements = array('Container', 'Footnote', 'Image', 'Link', 'ListItem', 'Table', 'Title'); + $elements = array('Container', 'Footnote', 'Image', 'Link', 'ListItem', 'Table', 'Title', 'Bookmark'); foreach ($elements as $element) { $objectClass = 'PhpOffice\\PhpWord\\Writer\\HTML\\Element\\' . $element; $parentWriter = new HTML(); diff --git a/tests/PhpWord/Writer/HTMLTest.php b/tests/PhpWord/Writer/HTMLTest.php index bdfc44e37d..f2bc717583 100644 --- a/tests/PhpWord/Writer/HTMLTest.php +++ b/tests/PhpWord/Writer/HTMLTest.php @@ -73,6 +73,7 @@ public function testSave() ); $phpWord->addParagraphStyle('Paragraph', array('alignment' => Jc::CENTER, 'spaceAfter' => 20, 'spaceBefore' => 20)); $section = $phpWord->addSection(); + $section->addBookmark('top'); $section->addText(htmlspecialchars('Test 1', ENT_COMPAT, 'UTF-8'), 'Font', 'Paragraph'); $section->addTextBreak(); $section->addText( @@ -128,6 +129,7 @@ public function testSave() $cell->addFootnote(); $cell->addEndnote(); $cell = $table->addRow()->addCell(); + $section->addLink('top', 'back to top', null, null, true); $writer = new HTML($phpWord); From 5ff15e06a2b2e0da4716567f20b05a89aaa7d018 Mon Sep 17 00:00:00 2001 From: troosan Date: Sun, 11 Feb 2018 00:17:19 +0100 Subject: [PATCH 026/135] update testing instructions [ci skip] --- docs/PULL_REQUEST_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/PULL_REQUEST_TEMPLATE.md b/docs/PULL_REQUEST_TEMPLATE.md index cff513a356..24ba001cff 100644 --- a/docs/PULL_REQUEST_TEMPLATE.md +++ b/docs/PULL_REQUEST_TEMPLATE.md @@ -6,6 +6,6 @@ Fixes # (issue) ### Checklist: -- [ ] I have run `composer check` and no errors were reported -- [ ] The new code is covered by unit tests +- [ ] I have run `composer run-script check --timeout=0` and no errors were reported +- [ ] The new code is covered by unit tests (check build/coverage for coverage report) - [ ] I have update the documentation to describe the changes From e846602d1ebdab8603b8c8b7d1b69a0577d3f780 Mon Sep 17 00:00:00 2001 From: troosan Date: Sun, 11 Feb 2018 13:58:26 +0100 Subject: [PATCH 027/135] fix null check [ci skip] --- src/PhpWord/Element/Image.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PhpWord/Element/Image.php b/src/PhpWord/Element/Image.php index 7eff87bc78..5e73d4e495 100644 --- a/src/PhpWord/Element/Image.php +++ b/src/PhpWord/Element/Image.php @@ -313,7 +313,7 @@ public function getImageStringData($base64 = false) $zip = new ZipArchive(); if ($zip->open($zipFilename) !== false) { - if ($zip->locateName($imageFilename)) { + if ($zip->locateName($imageFilename) !== false) { $isTemp = true; $zip->extractTo(Settings::getTempDir(), $imageFilename); $actualSource = Settings::getTempDir() . DIRECTORY_SEPARATOR . $imageFilename; @@ -458,7 +458,7 @@ private function getArchiveImageSize($source) $zip = new ZipArchive(); if ($zip->open($zipFilename) !== false) { - if ($zip->locateName($imageFilename)) { + if ($zip->locateName($imageFilename) !== false) { $imageContent = $zip->getFromName($imageFilename); if ($imageContent !== false) { file_put_contents($tempFilename, $imageContent); From 7ddaed240f46398166855c807c5256330e048738 Mon Sep 17 00:00:00 2001 From: ale rimoldi Date: Mon, 25 Jul 2016 10:11:52 +0200 Subject: [PATCH 028/135] table->setStretch() optionally avoids the table to stretch to the page width (only for word output) --- src/PhpWord/Style/Table.php | 33 +++++++++++++++++++++ src/PhpWord/Writer/Word2007/Style/Table.php | 15 ++++++++++ 2 files changed, 48 insertions(+) diff --git a/src/PhpWord/Style/Table.php b/src/PhpWord/Style/Table.php index a3d454f3aa..aa39794975 100644 --- a/src/PhpWord/Style/Table.php +++ b/src/PhpWord/Style/Table.php @@ -28,6 +28,8 @@ class Table extends Border const WIDTH_AUTO = 'auto'; // Automatically determined width const WIDTH_PERCENT = 'pct'; // Width in fiftieths (1/50) of a percent (1% = 50 unit) const WIDTH_TWIP = 'dxa'; // Width in twentieths (1/20) of a point (twip) + const STRETCH_AUTO = 'autofit'; // Automatically stretch the table to fit the page width + const STRETCH_FIXED = 'fixed'; // Do not stretch the table to fit the page width /** * Is this a first row style? @@ -121,6 +123,11 @@ class Table extends Border */ private $unit = self::WIDTH_AUTO; + /** + * @var string Stretch the table to the page width + */ + private $stretch = self::STRETCH_AUTO; + /** * Create new table style * @@ -582,6 +589,32 @@ public function setUnit($value = null) return $this; } + /** + * Get stretch + * + * @return string + */ + public function getStretch() + { + return $this->stretch; + } + + /** + * Set stretch + * + * Stretch the table to the page width + * + * @param string $value + * @return self + */ + public function setStretch($value = null) + { + $enum = array(self::STRETCH_AUTO, self::STRETCH_FIXED); + $this->stretch = $this->setEnumVal($value, $enum, $this->stretch); + + return $this; + } + /** * Get table style only property by checking if it's a firstRow * diff --git a/src/PhpWord/Writer/Word2007/Style/Table.php b/src/PhpWord/Writer/Word2007/Style/Table.php index 620e4fbf62..2c4066f117 100644 --- a/src/PhpWord/Writer/Word2007/Style/Table.php +++ b/src/PhpWord/Writer/Word2007/Style/Table.php @@ -77,6 +77,7 @@ private function writeStyle(XMLWriter $xmlWriter, TableStyle $style) } $this->writeWidth($xmlWriter, $style->getWidth(), $style->getUnit()); + $this->writeLayout($xmlWriter, $style->getStretch()); $this->writeMargin($xmlWriter, $style); $this->writeBorder($xmlWriter, $style); @@ -106,6 +107,20 @@ private function writeWidth(XMLWriter $xmlWriter, $width, $unit) $xmlWriter->endElement(); // w:tblW } + /** + * Enable/Disable automatic resizing of the table + * + * @param \PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param string $layout autofit / fixed + * @return void + */ + private function writeLayout(XMLWriter $xmlWriter, $stretch) + { + $xmlWriter->startElement('w:tblLayout'); + $xmlWriter->writeAttribute('w:type', $stretch); + $xmlWriter->endElement(); // w:tblLayout + } + /** * Write margin. * From 6a926e26f136a41937c8f5aa2eaef79d40cadcd8 Mon Sep 17 00:00:00 2001 From: troosan Date: Wed, 14 Feb 2018 00:39:37 +0100 Subject: [PATCH 029/135] refactor attribute name to layout, add doc and tests --- CHANGELOG.md | 1 + docs/styles.rst | 1 + src/PhpWord/Reader/Word2007/AbstractPart.php | 1 + src/PhpWord/Style/Table.php | 36 +++++++----- src/PhpWord/Writer/Word2007/Style/Table.php | 7 +-- tests/PhpWord/Element/ImageTest.php | 21 +++++++ tests/PhpWord/Reader/Word2007/StyleTest.php | 46 +++++++++++++++ tests/PhpWord/Style/TableTest.php | 11 ++++ .../Writer/Word2007/Style/TableTest.php | 58 +++++++++++++++++++ 9 files changed, 165 insertions(+), 17 deletions(-) create mode 100644 tests/PhpWord/Reader/Word2007/StyleTest.php create mode 100644 tests/PhpWord/Writer/Word2007/Style/TableTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 344517c799..762bf560be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ v0.15.0 (?? ??? 2018) - Parse formatting inside HTML lists - @troosan @samimussbach #1239 #945 #1215 #508 - Parsing of CSS `direction` instruction, HTML `lang` attribute, formatting inside table cell - @troosan #1273 #1252 #1254 - Add support for Track changes @Cip @troosan #354 #1262 +- Add support for fixed Table Layout @aoloe @ekopach @troosan #841 #1276 ### Fixed - Fix reading of docx default style - @troosan #1238 diff --git a/docs/styles.rst b/docs/styles.rst index 6166f5c9b2..031f37591c 100644 --- a/docs/styles.rst +++ b/docs/styles.rst @@ -103,6 +103,7 @@ Available Table style options: - ``border(Top|Right|Bottom|Left)Size``. Border size in twips. - ``cellMargin(Top|Right|Bottom|Left)``. Cell margin in twips. - ``width``. Table width in percent. +- ``layout``. Table layout, either *fixed* or *autofit* See ``\PhpOffice\PhpWord\Style\Table`` for constants. Available Row style options: diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 9276823b10..09d32dbb1e 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -425,6 +425,7 @@ protected function readTableStyle(XMLReader $xmlReader, \DOMElement $domNode) $styleDefs["border{$ucfSide}Color"] = array(self::READ_VALUE, "w:tblBorders/w:$side", 'w:color'); $styleDefs["border{$ucfSide}Style"] = array(self::READ_VALUE, "w:tblBorders/w:$side", 'w:val'); } + $styleDefs['layout'] = array(self::READ_VALUE, 'w:tblLayout', 'w:type'); $style = $this->readStyleDefs($xmlReader, $styleNode, $styleDefs); } } diff --git a/src/PhpWord/Style/Table.php b/src/PhpWord/Style/Table.php index aa39794975..d0ff47ede2 100644 --- a/src/PhpWord/Style/Table.php +++ b/src/PhpWord/Style/Table.php @@ -28,8 +28,20 @@ class Table extends Border const WIDTH_AUTO = 'auto'; // Automatically determined width const WIDTH_PERCENT = 'pct'; // Width in fiftieths (1/50) of a percent (1% = 50 unit) const WIDTH_TWIP = 'dxa'; // Width in twentieths (1/20) of a point (twip) - const STRETCH_AUTO = 'autofit'; // Automatically stretch the table to fit the page width - const STRETCH_FIXED = 'fixed'; // Do not stretch the table to fit the page width + + //values for http://www.datypic.com/sc/ooxml/t-w_ST_TblLayoutType.html + /** + * AutoFit Table Layout + * + * @var string + */ + const LAYOUT_AUTO = 'autofit'; + /** + * Fixed Width Table Layout + * + * @var string + */ + const LAYOUT_FIXED = 'fixed'; /** * Is this a first row style? @@ -124,9 +136,9 @@ class Table extends Border private $unit = self::WIDTH_AUTO; /** - * @var string Stretch the table to the page width + * @var string Table Layout */ - private $stretch = self::STRETCH_AUTO; + private $layout = self::LAYOUT_AUTO; /** * Create new table style @@ -590,27 +602,25 @@ public function setUnit($value = null) } /** - * Get stretch + * Get layout * * @return string */ - public function getStretch() + public function getLayout() { - return $this->stretch; + return $this->layout; } /** - * Set stretch - * - * Stretch the table to the page width + * Set layout * * @param string $value * @return self */ - public function setStretch($value = null) + public function setLayout($value = null) { - $enum = array(self::STRETCH_AUTO, self::STRETCH_FIXED); - $this->stretch = $this->setEnumVal($value, $enum, $this->stretch); + $enum = array(self::LAYOUT_AUTO, self::LAYOUT_FIXED); + $this->layout = $this->setEnumVal($value, $enum, $this->layout); return $this; } diff --git a/src/PhpWord/Writer/Word2007/Style/Table.php b/src/PhpWord/Writer/Word2007/Style/Table.php index 26df843630..e2e8f978dc 100644 --- a/src/PhpWord/Writer/Word2007/Style/Table.php +++ b/src/PhpWord/Writer/Word2007/Style/Table.php @@ -77,7 +77,7 @@ private function writeStyle(XMLWriter $xmlWriter, TableStyle $style) } $this->writeWidth($xmlWriter, $style->getWidth(), $style->getUnit()); - $this->writeLayout($xmlWriter, $style->getStretch()); + $this->writeLayout($xmlWriter, $style->getLayout()); $this->writeMargin($xmlWriter, $style); $this->writeBorder($xmlWriter, $style); @@ -112,12 +112,11 @@ private function writeWidth(XMLWriter $xmlWriter, $width, $unit) * * @param \PhpOffice\Common\XMLWriter $xmlWriter * @param string $layout autofit / fixed - * @return void */ - private function writeLayout(XMLWriter $xmlWriter, $stretch) + private function writeLayout(XMLWriter $xmlWriter, $layout) { $xmlWriter->startElement('w:tblLayout'); - $xmlWriter->writeAttribute('w:type', $stretch); + $xmlWriter->writeAttribute('w:type', $layout); $xmlWriter->endElement(); // w:tblLayout } diff --git a/tests/PhpWord/Element/ImageTest.php b/tests/PhpWord/Element/ImageTest.php index 0966ea4d4c..8bebce9137 100644 --- a/tests/PhpWord/Element/ImageTest.php +++ b/tests/PhpWord/Element/ImageTest.php @@ -210,6 +210,27 @@ public function testConstructFromString() $this->assertNotNull($image->getImageStringData(true)); } + /** + * Test construct from GD + */ + public function testConstructFromGd() + { + $source = 'http://php.net/images/logos/php-icon.png'; + + $image = new Image($source); + $this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\Image', $image); + $this->assertEquals($source, $image->getSource()); + $this->assertEquals(md5($source), $image->getMediaId()); + $this->assertEquals('image/png', $image->getImageType()); + $this->assertEquals('png', $image->getImageExtension()); + $this->assertEquals('imagecreatefrompng', $image->getImageCreateFunction()); + $this->assertEquals('imagepng', $image->getImageFunction()); + $this->assertTrue($image->isMemImage()); + + $this->assertNotNull($image->getImageStringData()); + $this->assertNotNull($image->getImageStringData(true)); + } + /** * Test invalid string image * diff --git a/tests/PhpWord/Reader/Word2007/StyleTest.php b/tests/PhpWord/Reader/Word2007/StyleTest.php new file mode 100644 index 0000000000..ce59f4c3b4 --- /dev/null +++ b/tests/PhpWord/Reader/Word2007/StyleTest.php @@ -0,0 +1,46 @@ + + + + + '; + + $phpWord = $this->getDocumentFromString($documentXml); + + $elements = $this->get($phpWord->getSections(), 0)->getElements(); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]); + $this->assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle()); + $this->assertEquals(Table::LAYOUT_FIXED, $elements[0]->getStyle()->getLayout()); + } +} diff --git a/tests/PhpWord/Style/TableTest.php b/tests/PhpWord/Style/TableTest.php index 2d57b1b828..dafdeb31b8 100644 --- a/tests/PhpWord/Style/TableTest.php +++ b/tests/PhpWord/Style/TableTest.php @@ -172,4 +172,15 @@ public function testSetStyleValue() $object->getBorderColor() ); } + + /** + * Tests table layout + */ + public function testTableLayout() + { + $object = new Table(); + $this->assertEquals(Table::LAYOUT_AUTO, $object->getLayout()); + $object->setLayout(Table::LAYOUT_FIXED); + $this->assertEquals(Table::LAYOUT_FIXED, $object->getLayout()); + } } diff --git a/tests/PhpWord/Writer/Word2007/Style/TableTest.php b/tests/PhpWord/Writer/Word2007/Style/TableTest.php new file mode 100644 index 0000000000..a89dd61048 --- /dev/null +++ b/tests/PhpWord/Writer/Word2007/Style/TableTest.php @@ -0,0 +1,58 @@ +setLayout(Table::LAYOUT_FIXED); + + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + $table = $section->addTable($tableStyle); + $table->addRow(); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $path = '/w:document/w:body/w:tbl/w:tblPr/w:tblLayout'; + $this->assertTrue($doc->elementExists($path)); + $this->assertEquals(Table::LAYOUT_FIXED, $doc->getElementAttribute($path, 'w:type')); + } +} From e7232a715b26f77d75c2055e8f9259869d83cdf8 Mon Sep 17 00:00:00 2001 From: Frank Liepert Date: Fri, 16 Feb 2018 14:34:37 +0100 Subject: [PATCH 030/135] Use singular form of twip --- docs/elements.rst | 6 +++--- docs/general.rst | 2 +- docs/styles.rst | 28 ++++++++++++++-------------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/elements.rst b/docs/elements.rst index 7df3b16359..12d4690864 100644 --- a/docs/elements.rst +++ b/docs/elements.rst @@ -307,8 +307,8 @@ Your TOC can only be generated if you have add at least one title (See "Titles") Options for ``$tocStyle``: - ``tabLeader``. Fill type between the title text and the page number. Use the defined constants in ``\PhpOffice\PhpWord\Style\TOC``. -- ``tabPos``. The position of the tab where the page number appears in twips. -- ``indent``. The indent factor of the titles in twips. +- ``tabPos``. The position of the tab where the page number appears in twip. +- ``indent``. The indent factor of the titles in twip. Footnotes & endnotes -------------------- @@ -429,7 +429,7 @@ Line elements can be added to sections by using ``addLine``. Available line style attributes: -- ``weight``. Line width in twips. +- ``weight``. Line width in twip. - ``color``. Defines the color of stroke. - ``dash``. Line types: dash, rounddot, squaredot, dashdot, longdash, longdashdot, longdashdotdot. - ``beginArrow``. Start type of arrow: block, open, classic, diamond, oval. diff --git a/docs/general.rst b/docs/general.rst index 09a23cee35..99d8b3bac0 100644 --- a/docs/general.rst +++ b/docs/general.rst @@ -255,7 +255,7 @@ The base length unit in Open Office XML is twip. Twip means "TWentieth of an Inch Point", i.e. 1 twip = 1/1440 inch. You can use PHPWord helper functions to convert inches, centimeters, or -points to twips. +points to twip. .. code-block:: php diff --git a/docs/styles.rst b/docs/styles.rst index 031f37591c..8f462a8c77 100644 --- a/docs/styles.rst +++ b/docs/styles.rst @@ -11,26 +11,26 @@ Section Available Section style options: - ``borderBottomColor``. Border bottom color. -- ``borderBottomSize``. Border bottom size (in twips). +- ``borderBottomSize``. Border bottom size (in twip). - ``borderLeftColor``. Border left color. -- ``borderLeftSize``. Border left size (in twips). +- ``borderLeftSize``. Border left size (in twip). - ``borderRightColor``. Border right color. -- ``borderRightSize``. Border right size (in twips). +- ``borderRightSize``. Border right size (in twip). - ``borderTopColor``. Border top color. -- ``borderTopSize``. Border top size (in twips). +- ``borderTopSize``. Border top size (in twip). - ``breakType``. Section break type (nextPage, nextColumn, continuous, evenPage, oddPage). - ``colsNum``. Number of columns. - ``colsSpace``. Spacing between columns. - ``footerHeight``. Spacing to bottom of footer. - ``gutter``. Page gutter spacing. - ``headerHeight``. Spacing to top of header. -- ``marginTop``. Page margin top (in twips). -- ``marginLeft``. Page margin left (in twips). -- ``marginRight``. Page margin right (in twips). -- ``marginBottom``. Page margin bottom (in twips). +- ``marginTop``. Page margin top (in twip). +- ``marginLeft``. Page margin left (in twip). +- ``marginRight``. Page margin right (in twip). +- ``marginBottom``. Page margin bottom (in twip). - ``orientation``. Page orientation (``portrait``, which is default, or ``landscape``). -- ``pageSizeH``. Page height (in twips). Implicitly defined by ``orientation`` option. Any changes are discouraged. -- ``pageSizeW``. Page width (in twips). Implicitly defined by ``orientation`` option. Any changes are discouraged. +- ``pageSizeH``. Page height (in twip). Implicitly defined by ``orientation`` option. Any changes are discouraged. +- ``pageSizeW``. Page width (in twip). Implicitly defined by ``orientation`` option. Any changes are discouraged. .. _font-style: @@ -100,8 +100,8 @@ Available Table style options: See ``\PhpOffice\PhpWord\SimpleType\JcTable`` and ``\PhpOffice\PhpWord\SimpleType\Jc`` classes for the details. - ``bgColor``. Background color, e.g. '9966CC'. - ``border(Top|Right|Bottom|Left)Color``. Border color, e.g. '9966CC'. -- ``border(Top|Right|Bottom|Left)Size``. Border size in twips. -- ``cellMargin(Top|Right|Bottom|Left)``. Cell margin in twips. +- ``border(Top|Right|Bottom|Left)Size``. Border size in twip. +- ``cellMargin(Top|Right|Bottom|Left)``. Cell margin in twip. - ``width``. Table width in percent. - ``layout``. Table layout, either *fixed* or *autofit* See ``\PhpOffice\PhpWord\Style\Table`` for constants. @@ -115,13 +115,13 @@ Available Cell style options: - ``bgColor``. Background color, e.g. '9966CC'. - ``border(Top|Right|Bottom|Left)Color``. Border color, e.g. '9966CC'. -- ``border(Top|Right|Bottom|Left)Size``. Border size in twips. +- ``border(Top|Right|Bottom|Left)Size``. Border size in twip. - ``gridSpan``. Number of columns spanned. - ``textDirection(btLr|tbRl)``. Direction of text. You can use constants ``\PhpOffice\PhpWord\Style\Cell::TEXT_DIR_BTLR`` and ``\PhpOffice\PhpWord\Style\Cell::TEXT_DIR_TBRL`` - ``valign``. Vertical alignment, *top*, *center*, *both*, *bottom*. - ``vMerge``. *restart* or *continue*. -- ``width``. Cell width in twips. +- ``width``. Cell width in twip. .. _image-style: From ab978356c38ffda37a3d5302cce64d66721b7e37 Mon Sep 17 00:00:00 2001 From: Frank Liepert Date: Fri, 16 Feb 2018 14:40:31 +0100 Subject: [PATCH 031/135] Use same markup for describing unit of measurement --- docs/containers.rst | 2 +- docs/elements.rst | 6 +++--- docs/styles.rst | 28 ++++++++++++++-------------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/containers.rst b/docs/containers.rst index 3569cc50c0..dc194d5976 100644 --- a/docs/containers.rst +++ b/docs/containers.rst @@ -79,7 +79,7 @@ Below are the properties of the line numbering style. - ``start`` Line numbering starting value - ``increment`` Line number increments -- ``distance`` Distance between text and line numbering in twip +- ``distance`` Distance between text and line numbering in *twip* - ``restart`` Line numbering restart setting continuous\|newPage\|newSection diff --git a/docs/elements.rst b/docs/elements.rst index 12d4690864..d13abc5634 100644 --- a/docs/elements.rst +++ b/docs/elements.rst @@ -307,8 +307,8 @@ Your TOC can only be generated if you have add at least one title (See "Titles") Options for ``$tocStyle``: - ``tabLeader``. Fill type between the title text and the page number. Use the defined constants in ``\PhpOffice\PhpWord\Style\TOC``. -- ``tabPos``. The position of the tab where the page number appears in twip. -- ``indent``. The indent factor of the titles in twip. +- ``tabPos``. The position of the tab where the page number appears in *twip*. +- ``indent``. The indent factor of the titles in *twip*. Footnotes & endnotes -------------------- @@ -429,7 +429,7 @@ Line elements can be added to sections by using ``addLine``. Available line style attributes: -- ``weight``. Line width in twip. +- ``weight``. Line width in *twip*. - ``color``. Defines the color of stroke. - ``dash``. Line types: dash, rounddot, squaredot, dashdot, longdash, longdashdot, longdashdotdot. - ``beginArrow``. Start type of arrow: block, open, classic, diamond, oval. diff --git a/docs/styles.rst b/docs/styles.rst index 8f462a8c77..9d1cc4c5de 100644 --- a/docs/styles.rst +++ b/docs/styles.rst @@ -11,26 +11,26 @@ Section Available Section style options: - ``borderBottomColor``. Border bottom color. -- ``borderBottomSize``. Border bottom size (in twip). +- ``borderBottomSize``. Border bottom size in *twip*. - ``borderLeftColor``. Border left color. -- ``borderLeftSize``. Border left size (in twip). +- ``borderLeftSize``. Border left size in *twip*. - ``borderRightColor``. Border right color. -- ``borderRightSize``. Border right size (in twip). +- ``borderRightSize``. Border right size in *twip*. - ``borderTopColor``. Border top color. -- ``borderTopSize``. Border top size (in twip). +- ``borderTopSize``. Border top size in *twip*. - ``breakType``. Section break type (nextPage, nextColumn, continuous, evenPage, oddPage). - ``colsNum``. Number of columns. - ``colsSpace``. Spacing between columns. - ``footerHeight``. Spacing to bottom of footer. - ``gutter``. Page gutter spacing. - ``headerHeight``. Spacing to top of header. -- ``marginTop``. Page margin top (in twip). -- ``marginLeft``. Page margin left (in twip). -- ``marginRight``. Page margin right (in twip). -- ``marginBottom``. Page margin bottom (in twip). +- ``marginTop``. Page margin top in *twip*. +- ``marginLeft``. Page margin left in *twip*. +- ``marginRight``. Page margin right in *twip*. +- ``marginBottom``. Page margin bottom in *twip*. - ``orientation``. Page orientation (``portrait``, which is default, or ``landscape``). -- ``pageSizeH``. Page height (in twip). Implicitly defined by ``orientation`` option. Any changes are discouraged. -- ``pageSizeW``. Page width (in twip). Implicitly defined by ``orientation`` option. Any changes are discouraged. +- ``pageSizeH``. Page height in *twip*. Implicitly defined by ``orientation`` option. Any changes are discouraged. +- ``pageSizeW``. Page width in *twip*. Implicitly defined by ``orientation`` option. Any changes are discouraged. .. _font-style: @@ -100,8 +100,8 @@ Available Table style options: See ``\PhpOffice\PhpWord\SimpleType\JcTable`` and ``\PhpOffice\PhpWord\SimpleType\Jc`` classes for the details. - ``bgColor``. Background color, e.g. '9966CC'. - ``border(Top|Right|Bottom|Left)Color``. Border color, e.g. '9966CC'. -- ``border(Top|Right|Bottom|Left)Size``. Border size in twip. -- ``cellMargin(Top|Right|Bottom|Left)``. Cell margin in twip. +- ``border(Top|Right|Bottom|Left)Size``. Border size in *twip*. +- ``cellMargin(Top|Right|Bottom|Left)``. Cell margin in *twip*. - ``width``. Table width in percent. - ``layout``. Table layout, either *fixed* or *autofit* See ``\PhpOffice\PhpWord\Style\Table`` for constants. @@ -115,13 +115,13 @@ Available Cell style options: - ``bgColor``. Background color, e.g. '9966CC'. - ``border(Top|Right|Bottom|Left)Color``. Border color, e.g. '9966CC'. -- ``border(Top|Right|Bottom|Left)Size``. Border size in twip. +- ``border(Top|Right|Bottom|Left)Size``. Border size in *twip*. - ``gridSpan``. Number of columns spanned. - ``textDirection(btLr|tbRl)``. Direction of text. You can use constants ``\PhpOffice\PhpWord\Style\Cell::TEXT_DIR_BTLR`` and ``\PhpOffice\PhpWord\Style\Cell::TEXT_DIR_TBRL`` - ``valign``. Vertical alignment, *top*, *center*, *both*, *bottom*. - ``vMerge``. *restart* or *continue*. -- ``width``. Cell width in twip. +- ``width``. Cell width in *twip*. .. _image-style: From fede4f736eac05f0444eb5a6bad7875356b00c94 Mon Sep 17 00:00:00 2001 From: Frank Liepert Date: Fri, 16 Feb 2018 15:45:20 +0100 Subject: [PATCH 032/135] Add missing unit of measurement descriptions --- docs/styles.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/styles.rst b/docs/styles.rst index 9d1cc4c5de..8e155ca295 100644 --- a/docs/styles.rst +++ b/docs/styles.rst @@ -70,15 +70,15 @@ Available Paragraph style options: - ``alignment``. Supports all alignment modes since 1st Edition of ECMA-376 standard up till ISO/IEC 29500:2012. See ``\PhpOffice\PhpWord\SimpleType\Jc`` class for the details. - ``basedOn``. Parent style. -- ``hanging``. Hanging by how much. -- ``indent``. Indent by how much. +- ``hanging``. Hanging in *twip*. +- ``indent``. Indent in *twip*. - ``keepLines``. Keep all lines on one page, *true* or *false*. - ``keepNext``. Keep paragraph with next paragraph, *true* or *false*. - ``lineHeight``. Text line height, e.g. *1.0*, *1.5*, etc. - ``next``. Style for next paragraph. - ``pageBreakBefore``. Start paragraph on next page, *true* or *false*. -- ``spaceBefore``. Space before paragraph. -- ``spaceAfter``. Space after paragraph. +- ``spaceBefore``. Space before paragraph in *twip*. +- ``spaceAfter``. Space after paragraph in *twip*. - ``spacing``. Space between lines. - ``spacingLineRule``. Line Spacing Rule. *auto*, *exact*, *atLeast* - ``tabs``. Set of custom tab stops. From d061c6dc7c2a8bb21639300a8de5ab2b0d4c357a Mon Sep 17 00:00:00 2001 From: Frank Liepert Date: Thu, 15 Feb 2018 22:45:07 +0100 Subject: [PATCH 033/135] Remove zend-stdlib dependency --- composer.json | 1 - src/PhpWord/TemplateProcessor.php | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 614865d824..bceb599818 100644 --- a/composer.json +++ b/composer.json @@ -61,7 +61,6 @@ "php": "^5.3.3 || ^7.0", "ext-xml": "*", "zendframework/zend-escaper": "^2.2", - "zendframework/zend-stdlib": "^2.2 || ^3.0", "phpoffice/common": "^0.2" }, "require-dev": { diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index 5dd7b0bfd4..269b25e95e 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -17,13 +17,13 @@ namespace PhpOffice\PhpWord; +use PhpOffice\Common\Text; use PhpOffice\PhpWord\Escaper\RegExp; use PhpOffice\PhpWord\Escaper\Xml; use PhpOffice\PhpWord\Exception\CopyFileException; use PhpOffice\PhpWord\Exception\CreateTemporaryFileException; use PhpOffice\PhpWord\Exception\Exception; use PhpOffice\PhpWord\Shared\ZipArchive; -use Zend\Stdlib\StringUtils; class TemplateProcessor { @@ -192,7 +192,7 @@ protected static function ensureMacroCompleted($macro) */ protected static function ensureUtf8Encoded($subject) { - if (!StringUtils::isValidUtf8($subject)) { + if (!Text::isUTF8($subject)) { $subject = utf8_encode($subject); } From ba035185c7f50cf66e78589cd158b22e516ddb8d Mon Sep 17 00:00:00 2001 From: troosan Date: Sun, 18 Feb 2018 00:09:14 +0100 Subject: [PATCH 034/135] point next dev version to develop branch [ci skip] --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index bceb599818..d1c35b40f4 100644 --- a/composer.json +++ b/composer.json @@ -88,7 +88,7 @@ }, "extra": { "branch-alias": { - "dev-master": "0.15-dev" + "dev-develop": "0.15-dev" } } } From 04d0c02e2374624bfb408da42fb4e81bcdbfe362 Mon Sep 17 00:00:00 2001 From: dox07 Date: Sun, 18 Feb 2018 02:10:10 +0300 Subject: [PATCH 035/135] Add support for cellSpacing for tables (#1040) * Add cellSpacing into table * add word 2007 reader * add tests * add documentation --- CHANGELOG.md | 3 +- docs/styles.rst | 2 + samples/Sample_09_Tables.php | 2 +- src/PhpWord/Reader/Word2007/AbstractPart.php | 1 + src/PhpWord/SimpleType/TblWidth.php | 42 +++++++++++++++++++ src/PhpWord/Style/Table.php | 38 ++++++++++++++--- src/PhpWord/Writer/Word2007/Style/Table.php | 40 ++++++++++-------- tests/PhpWord/Reader/Word2007/StyleTest.php | 23 ++++++++++ tests/PhpWord/Style/TableTest.php | 28 +++++++++---- .../Writer/Word2007/Style/TableTest.php | 21 ++++++++++ 10 files changed, 168 insertions(+), 32 deletions(-) create mode 100644 src/PhpWord/SimpleType/TblWidth.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 762bf560be..2dca83487b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,12 @@ This project adheres to [Semantic Versioning](http://semver.org/). v0.15.0 (?? ??? 2018) ---------------------- ### Added -- Parsing of "align" HTML attribute - @troosan #1231 +- Parsing of `align` HTML attribute - @troosan #1231 - Parse formatting inside HTML lists - @troosan @samimussbach #1239 #945 #1215 #508 - Parsing of CSS `direction` instruction, HTML `lang` attribute, formatting inside table cell - @troosan #1273 #1252 #1254 - Add support for Track changes @Cip @troosan #354 #1262 - Add support for fixed Table Layout @aoloe @ekopach @troosan #841 #1276 +- Add support for Cell Spacing @dox07 @troosan #1040 ### Fixed - Fix reading of docx default style - @troosan #1238 diff --git a/docs/styles.rst b/docs/styles.rst index 8e155ca295..0ec0ec38d5 100644 --- a/docs/styles.rst +++ b/docs/styles.rst @@ -103,7 +103,9 @@ Available Table style options: - ``border(Top|Right|Bottom|Left)Size``. Border size in *twip*. - ``cellMargin(Top|Right|Bottom|Left)``. Cell margin in *twip*. - ``width``. Table width in percent. +- ``unit``. The unit to use for the width. One of ``\PhpOffice\PhpWord\SimpleType\TblWidth``. Defaults to *auto*. - ``layout``. Table layout, either *fixed* or *autofit* See ``\PhpOffice\PhpWord\Style\Table`` for constants. +- ``cellSpacing`` Cell spacing in *twip* Available Row style options: diff --git a/samples/Sample_09_Tables.php b/samples/Sample_09_Tables.php index c4be7c9eaf..ba41aa5484 100644 --- a/samples/Sample_09_Tables.php +++ b/samples/Sample_09_Tables.php @@ -27,7 +27,7 @@ $section->addText('Fancy table', $header); $fancyTableStyleName = 'Fancy Table'; -$fancyTableStyle = array('borderSize' => 6, 'borderColor' => '006699', 'cellMargin' => 80, 'alignment' => \PhpOffice\PhpWord\SimpleType\JcTable::CENTER); +$fancyTableStyle = array('borderSize' => 6, 'borderColor' => '006699', 'cellMargin' => 80, 'alignment' => \PhpOffice\PhpWord\SimpleType\JcTable::CENTER, 'cellSpacing' => 50); $fancyTableFirstRowStyle = array('borderBottomSize' => 18, 'borderBottomColor' => '0000FF', 'bgColor' => '66BBFF'); $fancyTableCellStyle = array('valign' => 'center'); $fancyTableCellBtlrStyle = array('valign' => 'center', 'textDirection' => \PhpOffice\PhpWord\Style\Cell::TEXT_DIR_BTLR); diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 09d32dbb1e..511e90813d 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -426,6 +426,7 @@ protected function readTableStyle(XMLReader $xmlReader, \DOMElement $domNode) $styleDefs["border{$ucfSide}Style"] = array(self::READ_VALUE, "w:tblBorders/w:$side", 'w:val'); } $styleDefs['layout'] = array(self::READ_VALUE, 'w:tblLayout', 'w:type'); + $styleDefs['cellSpacing'] = array(self::READ_VALUE, 'w:tblCellSpacing', 'w:w'); $style = $this->readStyleDefs($xmlReader, $styleNode, $styleDefs); } } diff --git a/src/PhpWord/SimpleType/TblWidth.php b/src/PhpWord/SimpleType/TblWidth.php new file mode 100644 index 0000000000..3d947bce7c --- /dev/null +++ b/src/PhpWord/SimpleType/TblWidth.php @@ -0,0 +1,42 @@ +firstRowStyle = clone $this; $this->firstRowStyle->isFirstRow = true; - unset($this->firstRowStyle->firstRowStyle, $this->firstRowStyle->borderInsideHSize, $this->firstRowStyle->borderInsideHColor, $this->firstRowStyle->borderInsideVSize, $this->firstRowStyle->borderInsideVColor, $this->firstRowStyle->cellMarginTop, $this->firstRowStyle->cellMarginLeft, $this->firstRowStyle->cellMarginRight, $this->firstRowStyle->cellMarginBottom); + unset($this->firstRowStyle->firstRowStyle, $this->firstRowStyle->borderInsideHSize, $this->firstRowStyle->borderInsideHColor, $this->firstRowStyle->borderInsideVSize, $this->firstRowStyle->borderInsideVColor, $this->firstRowStyle->cellMarginTop, $this->firstRowStyle->cellMarginLeft, $this->firstRowStyle->cellMarginRight, $this->firstRowStyle->cellMarginBottom, $this->firstRowStyle->cellSpacing); $this->firstRowStyle->setStyleByArray($firstRowStyle); } @@ -161,6 +173,22 @@ public function __construct($tableStyle = null, $firstRowStyle = null) } } + /** + * @param float|int $cellSpacing + */ + public function setCellSpacing($cellSpacing = null) + { + $this->cellSpacing = $cellSpacing; + } + + /** + * @return float|int + */ + public function getCellSpacing() + { + return $this->cellSpacing; + } + /** * Set first row * @@ -595,8 +623,8 @@ public function getUnit() */ public function setUnit($value = null) { - $enum = array(self::WIDTH_AUTO, self::WIDTH_PERCENT, self::WIDTH_TWIP); - $this->unit = $this->setEnumVal($value, $enum, $this->unit); + TblWidth::validate($value); + $this->unit = $value; return $this; } diff --git a/src/PhpWord/Writer/Word2007/Style/Table.php b/src/PhpWord/Writer/Word2007/Style/Table.php index e2e8f978dc..1422621251 100644 --- a/src/PhpWord/Writer/Word2007/Style/Table.php +++ b/src/PhpWord/Writer/Word2007/Style/Table.php @@ -18,6 +18,7 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Style; use PhpOffice\Common\XMLWriter; +use PhpOffice\PhpWord\SimpleType\TblWidth; use PhpOffice\PhpWord\Style\Table as TableStyle; use PhpOffice\PhpWord\Writer\Word2007\Element\TableAlignment; @@ -49,7 +50,7 @@ public function write() $xmlWriter->writeAttribute('w:val', $style); $xmlWriter->endElement(); if (null !== $this->width) { - $this->writeWidth($xmlWriter, $this->width, 'pct'); + $this->writeTblWidth($xmlWriter, 'w:tblW', TblWidth::PERCENT, $this->width); } $xmlWriter->endElement(); } @@ -76,7 +77,8 @@ private function writeStyle(XMLWriter $xmlWriter, TableStyle $style) $xmlWriter->endElement(); } - $this->writeWidth($xmlWriter, $style->getWidth(), $style->getUnit()); + $this->writeTblWidth($xmlWriter, 'w:tblW', $style->getUnit(), $style->getWidth()); + $this->writeTblWidth($xmlWriter, 'w:tblCellSpacing', TblWidth::TWIP, $style->getCellSpacing()); $this->writeLayout($xmlWriter, $style->getLayout()); $this->writeMargin($xmlWriter, $style); $this->writeBorder($xmlWriter, $style); @@ -92,21 +94,6 @@ private function writeStyle(XMLWriter $xmlWriter, TableStyle $style) } } - /** - * Write width. - * - * @param \PhpOffice\Common\XMLWriter $xmlWriter - * @param int $width - * @param string $unit - */ - private function writeWidth(XMLWriter $xmlWriter, $width, $unit) - { - $xmlWriter->startElement('w:tblW'); - $xmlWriter->writeAttribute('w:w', $width); - $xmlWriter->writeAttribute('w:type', $unit); - $xmlWriter->endElement(); // w:tblW - } - /** * Enable/Disable automatic resizing of the table * @@ -159,6 +146,25 @@ private function writeBorder(XMLWriter $xmlWriter, TableStyle $style) } } + /** + * Writes a table width + * + * @param \PhpOffice\Common\XMLWriter $xmlWriter + * @param string $elementName + * @param string $unit + * @param int|float $width + */ + private function writeTblWidth(XMLWriter $xmlWriter, $elementName, $unit, $width = null) + { + if (null === $width) { + return; + } + $xmlWriter->startElement($elementName); + $xmlWriter->writeAttributeIf(null !== $width, 'w:w', $width); + $xmlWriter->writeAttribute('w:type', $unit); + $xmlWriter->endElement(); + } + /** * Write row style. * diff --git a/tests/PhpWord/Reader/Word2007/StyleTest.php b/tests/PhpWord/Reader/Word2007/StyleTest.php index ce59f4c3b4..4375df475a 100644 --- a/tests/PhpWord/Reader/Word2007/StyleTest.php +++ b/tests/PhpWord/Reader/Word2007/StyleTest.php @@ -18,6 +18,7 @@ namespace PhpOffice\PhpWord\Reader\Word2007; use PhpOffice\PhpWord\AbstractTestReader; +use PhpOffice\PhpWord\SimpleType\TblWidth; use PhpOffice\PhpWord\Style\Table; /** @@ -43,4 +44,26 @@ public function testReadTableLayout() $this->assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle()); $this->assertEquals(Table::LAYOUT_FIXED, $elements[0]->getStyle()->getLayout()); } + + /** + * Test reading of cell spacing + */ + public function testReadCellSpacing() + { + $documentXml = ' + + + + '; + + $phpWord = $this->getDocumentFromString($documentXml); + + $elements = $this->get($phpWord->getSections(), 0)->getElements(); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]); + $this->assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle()); + $this->assertEquals(TblWidth::AUTO, $elements[0]->getStyle()->getUnit()); + /** @var \PhpOffice\PhpWord\Style\Table $tableStyle */ + $tableStyle = $elements[0]->getStyle(); + $this->assertEquals(10.5, $tableStyle->getCellSpacing()); + } } diff --git a/tests/PhpWord/Style/TableTest.php b/tests/PhpWord/Style/TableTest.php index dafdeb31b8..9dec422e97 100644 --- a/tests/PhpWord/Style/TableTest.php +++ b/tests/PhpWord/Style/TableTest.php @@ -18,6 +18,7 @@ namespace PhpOffice\PhpWord\Style; use PhpOffice\PhpWord\SimpleType\JcTable; +use PhpOffice\PhpWord\SimpleType\TblWidth; /** * Test class for PhpOffice\PhpWord\Style\Table @@ -38,9 +39,6 @@ public function testConstruct() $styleTable = array('bgColor' => 'FF0000'); $styleFirstRow = array('borderBottomSize' => 3); - $object = new Table(); - $this->assertNull($object->getBgColor()); - $object = new Table($styleTable, $styleFirstRow); $this->assertEquals('FF0000', $object->getBgColor()); @@ -49,6 +47,18 @@ public function testConstruct() $this->assertEquals(3, $firstRow->getBorderBottomSize()); } + /** + * Test default values when passing no style + */ + public function testDefaultValues() + { + $object = new Table(); + + $this->assertNull($object->getBgColor()); + $this->assertEquals(Table::LAYOUT_AUTO, $object->getLayout()); + $this->assertEquals(TblWidth::AUTO, $object->getUnit()); + } + /** * Test setting style with normal value */ @@ -77,6 +87,7 @@ public function testSetGetNormal() 'alignment' => JcTable::CENTER, 'width' => 100, 'unit' => 'pct', + 'layout' => Table::LAYOUT_FIXED, ); foreach ($attributes as $key => $value) { $set = "set{$key}"; @@ -174,13 +185,14 @@ public function testSetStyleValue() } /** - * Tests table layout + * Tests table cell spacing */ - public function testTableLayout() + public function testTableCellSpacing() { $object = new Table(); - $this->assertEquals(Table::LAYOUT_AUTO, $object->getLayout()); - $object->setLayout(Table::LAYOUT_FIXED); - $this->assertEquals(Table::LAYOUT_FIXED, $object->getLayout()); + $this->assertNull($object->getCellSpacing()); + + $object = new Table(array('cellSpacing' => 20)); + $this->assertEquals(20, $object->getCellSpacing()); } } diff --git a/tests/PhpWord/Writer/Word2007/Style/TableTest.php b/tests/PhpWord/Writer/Word2007/Style/TableTest.php index a89dd61048..c0a0b3ad13 100644 --- a/tests/PhpWord/Writer/Word2007/Style/TableTest.php +++ b/tests/PhpWord/Writer/Word2007/Style/TableTest.php @@ -55,4 +55,25 @@ public function testTableLayout() $this->assertTrue($doc->elementExists($path)); $this->assertEquals(Table::LAYOUT_FIXED, $doc->getElementAttribute($path, 'w:type')); } + + /** + * Test write styles + */ + public function testCellSpacing() + { + $tableStyle = new Table(); + $tableStyle->setCellSpacing(10.3); + + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + $table = $section->addTable($tableStyle); + $table->addRow(); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $path = '/w:document/w:body/w:tbl/w:tblPr/w:tblCellSpacing'; + $this->assertTrue($doc->elementExists($path)); + $this->assertEquals(10.3, $doc->getElementAttribute($path, 'w:w')); + $this->assertEquals(\PhpOffice\PhpWord\SimpleType\TblWidth::TWIP, $doc->getElementAttribute($path, 'w:type')); + } } From bded91af9f9a28927263484ac98e9190c20f9c94 Mon Sep 17 00:00:00 2001 From: troosan Date: Sun, 18 Feb 2018 00:39:00 +0100 Subject: [PATCH 036/135] Footnote in listitem (#1289) * Allow footnote to be added in ListItems --- CHANGELOG.md | 1 + samples/Sample_14_ListItem.php | 2 ++ src/PhpWord/Element/AbstractContainer.php | 2 +- src/PhpWord/Shared/Html.php | 10 +++++++--- src/PhpWord/Style/Cell.php | 6 ++++-- 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2dca83487b..406122b6af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ v0.15.0 (?? ??? 2018) - Save PNG alpha information when using remote images. @samsullivan #779 - Fix parsing of `` tag. @troosan #1274 - Bookmark are not writton as internal link in html writer @troosan #1263 +- It should be possible to add a Footnote in a ListItemRun @troosan #1287 #1287 diff --git a/samples/Sample_14_ListItem.php b/samples/Sample_14_ListItem.php index 689ac3d3eb..774fd284d0 100644 --- a/samples/Sample_14_ListItem.php +++ b/samples/Sample_14_ListItem.php @@ -67,6 +67,8 @@ $listItemRun = $section->addListItemRun(); $listItemRun->addText('List item 2'); $listItemRun->addText(' in italic', array('italic' => true)); +$footnote = $listItemRun->addFootnote(); +$footnote->addText('this is a footnote on a list item'); $listItemRun = $section->addListItemRun(); $listItemRun->addText('List item 3'); $listItemRun->addText(' underlined', array('underline' => 'dash')); diff --git a/src/PhpWord/Element/AbstractContainer.php b/src/PhpWord/Element/AbstractContainer.php index 4a5f83f536..507ff143e5 100644 --- a/src/PhpWord/Element/AbstractContainer.php +++ b/src/PhpWord/Element/AbstractContainer.php @@ -207,7 +207,7 @@ private function checkValidity($method) 'Table' => array('Section', 'Header', 'Footer', 'Cell', 'TextBox'), 'CheckBox' => array('Section', 'Header', 'Footer', 'Cell', 'TextRun'), 'TextBox' => array('Section', 'Header', 'Footer', 'Cell'), - 'Footnote' => array('Section', 'TextRun', 'Cell'), + 'Footnote' => array('Section', 'TextRun', 'Cell', 'ListItemRun'), 'Endnote' => array('Section', 'TextRun', 'Cell'), 'PreserveText' => array('Section', 'Header', 'Footer', 'Cell'), 'Title' => array('Section', 'Cell'), diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 971776ff93..1841616ece 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -415,6 +415,10 @@ private static function parseList($node, $element, &$styles, &$data) } } + /** + * @param bool $isOrderedList + * @return array + */ private static function getListStyle($isOrderedList) { if ($isOrderedList) { @@ -547,13 +551,13 @@ private static function parseStyle($attribute, $styles) case 'width': if (preg_match('/([0-9]+[a-z]+)/', $cValue, $matches)) { $styles['width'] = Converter::cssToTwip($matches[1]); - $styles['unit'] = \PhpOffice\PhpWord\Style\Table::WIDTH_TWIP; + $styles['unit'] = \PhpOffice\PhpWord\SimpleType\TblWidth::TWIP; } elseif (preg_match('/([0-9]+)%/', $cValue, $matches)) { $styles['width'] = $matches[1] * 50; - $styles['unit'] = \PhpOffice\PhpWord\Style\Table::WIDTH_PERCENT; + $styles['unit'] = \PhpOffice\PhpWord\SimpleType\TblWidth::PERCENT; } elseif (preg_match('/([0-9]+)/', $cValue, $matches)) { $styles['width'] = $matches[1]; - $styles['unit'] = \PhpOffice\PhpWord\Style\Table::WIDTH_AUTO; + $styles['unit'] = \PhpOffice\PhpWord\SimpleType\TblWidth::AUTO; } break; case 'border': diff --git a/src/PhpWord/Style/Cell.php b/src/PhpWord/Style/Cell.php index c281f99872..8675ed7b11 100644 --- a/src/PhpWord/Style/Cell.php +++ b/src/PhpWord/Style/Cell.php @@ -17,6 +17,8 @@ namespace PhpOffice\PhpWord\Style; +use PhpOffice\PhpWord\SimpleType\TblWidth; + /** * Table cell style */ @@ -123,7 +125,7 @@ class Cell extends Border * * @var string */ - private $unit = Table::WIDTH_TWIP; + private $unit = TblWidth::TWIP; /** * Get vertical align. @@ -308,7 +310,7 @@ public function getUnit() */ public function setUnit($value) { - $this->unit = $this->setEnumVal($value, array(Table::WIDTH_AUTO, Table::WIDTH_PERCENT, Table::WIDTH_TWIP), Table::WIDTH_TWIP); + $this->unit = $this->setEnumVal($value, array(TblWidth::AUTO, TblWidth::PERCENT, TblWidth::TWIP), TblWidth::TWIP); return $this; } From 59de019881750f9cb2bbae7f005e56c65d545b6d Mon Sep 17 00:00:00 2001 From: troosan Date: Sun, 18 Feb 2018 01:41:32 +0100 Subject: [PATCH 037/135] Fix listitem parsing (#1290) * Word 2007 Reader: Added support for ListItemRun * Add tests + changelog --- CHANGELOG.md | 3 ++ samples/resources/Sample_11_ReadWord2007.docx | Bin 63320 -> 63388 bytes src/PhpWord/Reader/Word2007/AbstractPart.php | 9 ++-- tests/PhpWord/Reader/Word2007/ElementTest.php | 40 ++++++++++++++++++ 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 406122b6af..f6f87158a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ v0.15.0 (?? ??? 2018) - Add support for Track changes @Cip @troosan #354 #1262 - Add support for fixed Table Layout @aoloe @ekopach @troosan #841 #1276 - Add support for Cell Spacing @dox07 @troosan #1040 +- Add parsing of formatting inside lists @atomicalnet @troosan #594 ### Fixed - Fix reading of docx default style - @troosan #1238 @@ -22,6 +23,8 @@ v0.15.0 (?? ??? 2018) - Bookmark are not writton as internal link in html writer @troosan #1263 - It should be possible to add a Footnote in a ListItemRun @troosan #1287 #1287 +### Changed +- Remove zend-stdlib dependency @Trainmaster #1284 v0.14.0 (29 Dec 2017) diff --git a/samples/resources/Sample_11_ReadWord2007.docx b/samples/resources/Sample_11_ReadWord2007.docx index 3faf6f1213f13e82466ef29200862498d2ef7014..406cf1e1ebf296f563f7a05ef4c7c6aaaffd148b 100644 GIT binary patch delta 11671 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 Jef1Cb{{unDO-=v+ delta 11571 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 diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 511e90813d..1d61051652 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -138,14 +138,15 @@ protected function readParagraph(XMLReader $xmlReader, \DOMElement $domNode, $pa $parent->addPreserveText($textContent, $fontStyle, $paragraphStyle); } elseif ($xmlReader->elementExists('w:pPr/w:numPr', $domNode)) { // List item - $textContent = ''; $numId = $xmlReader->getAttribute('w:val', $domNode, 'w:pPr/w:numPr/w:numId'); $levelId = $xmlReader->getAttribute('w:val', $domNode, 'w:pPr/w:numPr/w:ilvl'); - $nodes = $xmlReader->getElements('w:r', $domNode); + $nodes = $xmlReader->getElements('*', $domNode); + + $listItemRun = $parent->addListItemRun($levelId, "PHPWordList{$numId}", $paragraphStyle); + foreach ($nodes as $node) { - $textContent .= $xmlReader->getValue('w:t', $node); + $this->readRun($xmlReader, $node, $listItemRun, $docPart, $paragraphStyle); } - $parent->addListItem($textContent, $levelId, null, "PHPWordList{$numId}", $paragraphStyle); } elseif (!empty($headingMatches)) { // Heading $textContent = ''; diff --git a/tests/PhpWord/Reader/Word2007/ElementTest.php b/tests/PhpWord/Reader/Word2007/ElementTest.php index 67c2eb1385..c2648b6839 100644 --- a/tests/PhpWord/Reader/Word2007/ElementTest.php +++ b/tests/PhpWord/Reader/Word2007/ElementTest.php @@ -43,4 +43,44 @@ public function testReadTextBreak() $this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $elements[1]); $this->assertEquals('test string', $elements[1]->getText()); } + + /** + * Test reading of textbreak + */ + public function testReadListItemRunWithFormatting() + { + $documentXml = ' + + + + + + + + Two + + + with + + + + + + bold + + '; + + $phpWord = $this->getDocumentFromString($documentXml); + + $elements = $this->get($phpWord->getSections(), 0)->getElements(); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\ListItemRun', $elements[0]); + $this->assertEquals(0, $elements[0]->getDepth()); + + $listElements = $this->get($elements, 0)->getElements(); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $listElements[0]); + $this->assertEquals('Two', $listElements[0]->getText()); + $this->assertEquals(' with ', $listElements[1]->getText()); + $this->assertEquals('bold', $listElements[2]->getText()); + $this->assertTrue($listElements[2]->getFontStyle()->getBold()); + } } From 557af99a6df894d5216dae3c58f0089779dafa05 Mon Sep 17 00:00:00 2001 From: Matt Bolt Date: Mon, 19 Feb 2018 12:43:01 +0800 Subject: [PATCH 038/135] Fix colspan and rowspan for tables in HTML Writer --- src/PhpWord/Writer/HTML/Element/Table.php | 57 +++++++++++++++++++---- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/src/PhpWord/Writer/HTML/Element/Table.php b/src/PhpWord/Writer/HTML/Element/Table.php index c7d8670b16..17ba04b534 100644 --- a/src/PhpWord/Writer/HTML/Element/Table.php +++ b/src/PhpWord/Writer/HTML/Element/Table.php @@ -40,18 +40,59 @@ public function write() $rowCount = count($rows); if ($rowCount > 0) { $content .= '' . PHP_EOL; - foreach ($rows as $row) { + for ($i = 0; $i < count($rows); $i++) { /** @var $row \PhpOffice\PhpWord\Element\Row Type hint */ - $rowStyle = $row->getStyle(); + $rowStyle = $rows[$i]->getStyle(); // $height = $row->getHeight(); $tblHeader = $rowStyle->isTblHeader(); $content .= '' . PHP_EOL; - foreach ($row->getCells() as $cell) { - $writer = new Container($this->parentWriter, $cell); - $cellTag = $tblHeader ? 'th' : 'td'; - $content .= "<{$cellTag}>" . PHP_EOL; - $content .= $writer->write(); - $content .= "" . PHP_EOL; + $rowCells = $rows[$i]->getCells(); + for ($j = 0; $j < count($rowCells); $j++) { + $cellStyle = $rowCells[$j]->getStyle(); + $cellColSpan = $cellStyle->getGridSpan(); + $cellRowSpan = 1; + $cellVMerge = $cellStyle->getVMerge(); + // If this is the first cell of the vertical merge, find out how man rows it spans + if ($cellVMerge === 'restart') { + for ($k = $i + 1; $k < count($rows); $k++) { + $kRowCells = $rows[$k]->getCells(); + if (isset($kRowCells[$j])) { + if ($kRowCells[$j]->getStyle()->getVMerge() === 'continue') { + $cellRowSpan++; + } else { + break; + } + } else { + break; + } + } + } + // Ignore cells that are merged vertically with previous rows + if ($cellVMerge !== 'continue') { + $cellTag = $tblHeader ? 'th' : 'td'; + $cellColSpanAttr = (is_numeric($cellColSpan) && ($cellColSpan > 1) ? " colspan=\"{$cellColSpan}\"" : ""); + $cellRowSpanAttr = ($cellRowSpan > 1 ? " rowspan=\"{$cellRowSpan}\"" : ""); + $content .= "<{$cellTag}{$cellColSpanAttr}{$cellRowSpanAttr}>" . PHP_EOL; + $writer = new Container($this->parentWriter, $rowCells[$j]); + $content .= $writer->write(); + if ($cellRowSpan > 1) { + // There shouldn't be any content in the subsequent merged cells, but lets check anyway + for ($k = $i + 1; $k < count($rows); $k++) { + $kRowCells = $rows[$k]->getCells(); + if (isset($kRowCells[$j])) { + if ($kRowCells[$j]->getStyle()->getVMerge() === 'continue') { + $writer = new Container($this->parentWriter, $kRowCells[$j]); + $content .= $writer->write(); + } else { + break; + } + } else { + break; + } + } + } + $content .= "" . PHP_EOL; + } } $content .= '' . PHP_EOL; } From a95c3f83bcc0bf99fe7c8b91e3d63f1161391794 Mon Sep 17 00:00:00 2001 From: Matt Bolt Date: Mon, 19 Feb 2018 18:02:55 +0800 Subject: [PATCH 039/135] Fix colspan and rowspan for tables in HTML Writer. Syntax improved. --- src/PhpWord/Writer/HTML/Element/Table.php | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/PhpWord/Writer/HTML/Element/Table.php b/src/PhpWord/Writer/HTML/Element/Table.php index 17ba04b534..30de239749 100644 --- a/src/PhpWord/Writer/HTML/Element/Table.php +++ b/src/PhpWord/Writer/HTML/Element/Table.php @@ -40,21 +40,22 @@ public function write() $rowCount = count($rows); if ($rowCount > 0) { $content .= '
      ' . PHP_EOL; - for ($i = 0; $i < count($rows); $i++) { + for ($i = 0; $i < $rowCount; $i++) { /** @var $row \PhpOffice\PhpWord\Element\Row Type hint */ $rowStyle = $rows[$i]->getStyle(); // $height = $row->getHeight(); $tblHeader = $rowStyle->isTblHeader(); $content .= '' . PHP_EOL; $rowCells = $rows[$i]->getCells(); - for ($j = 0; $j < count($rowCells); $j++) { + $rowCellCount = count($rowCells); + for ($j = 0; $j < $rowCellCount; $j++) { $cellStyle = $rowCells[$j]->getStyle(); $cellColSpan = $cellStyle->getGridSpan(); $cellRowSpan = 1; $cellVMerge = $cellStyle->getVMerge(); // If this is the first cell of the vertical merge, find out how man rows it spans if ($cellVMerge === 'restart') { - for ($k = $i + 1; $k < count($rows); $k++) { + for ($k = $i + 1; $k < $rowCount; $k++) { $kRowCells = $rows[$k]->getCells(); if (isset($kRowCells[$j])) { if ($kRowCells[$j]->getStyle()->getVMerge() === 'continue') { @@ -70,14 +71,14 @@ public function write() // Ignore cells that are merged vertically with previous rows if ($cellVMerge !== 'continue') { $cellTag = $tblHeader ? 'th' : 'td'; - $cellColSpanAttr = (is_numeric($cellColSpan) && ($cellColSpan > 1) ? " colspan=\"{$cellColSpan}\"" : ""); - $cellRowSpanAttr = ($cellRowSpan > 1 ? " rowspan=\"{$cellRowSpan}\"" : ""); + $cellColSpanAttr = (is_numeric($cellColSpan) && ($cellColSpan > 1) ? " colspan=\"{$cellColSpan}\"" : ''); + $cellRowSpanAttr = ($cellRowSpan > 1 ? " rowspan=\"{$cellRowSpan}\"" : ''); $content .= "<{$cellTag}{$cellColSpanAttr}{$cellRowSpanAttr}>" . PHP_EOL; $writer = new Container($this->parentWriter, $rowCells[$j]); $content .= $writer->write(); if ($cellRowSpan > 1) { // There shouldn't be any content in the subsequent merged cells, but lets check anyway - for ($k = $i + 1; $k < count($rows); $k++) { + for ($k = $i + 1; $k < $rowCount; $k++) { $kRowCells = $rows[$k]->getCells(); if (isset($kRowCells[$j])) { if ($kRowCells[$j]->getStyle()->getVMerge() === 'continue') { From f3c73f333adbbbc4c625dd599b2889889d1d29eb Mon Sep 17 00:00:00 2001 From: Samuel Laulhau Date: Tue, 27 Feb 2018 23:24:01 +0100 Subject: [PATCH 040/135] Fix HTML parsing when style attribute is empty (#1295) --- src/PhpWord/Shared/Html.php | 3 ++- tests/PhpWord/Shared/HtmlTest.php | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 1841616ece..7363580753 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -486,8 +486,9 @@ private static function parseListItem($node, $element, &$styles, $data) private static function parseStyle($attribute, $styles) { $properties = explode(';', trim($attribute->value, " \t\n\r\0\x0B;")); + foreach ($properties as $property) { - list($cKey, $cValue) = explode(':', $property, 2); + list($cKey, $cValue) = array_pad(explode(':', $property, 2), 2, null); $cValue = trim($cValue); switch (trim($cKey)) { case 'text-decoration': diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index ac68b8876c..8be1cc191c 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -418,4 +418,14 @@ public function testParseLink() $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:hyperlink')); $this->assertEquals('link text', $doc->getElement('/w:document/w:body/w:p/w:hyperlink/w:r/w:t')->nodeValue); } + + public function testParseMalformedStyleIsIgnored() + { + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + $html = '

      text

      '; + Html::addHtml($section, $html); + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + $this->assertFalse($doc->elementExists('/w:document/w:body/w:p[1]/w:pPr/w:jc')); + } } From 7fe32e6ac1b23ea039015f207184fd36e3f1a6bb Mon Sep 17 00:00:00 2001 From: Lenz Weber Date: Tue, 27 Feb 2018 23:27:18 +0100 Subject: [PATCH 041/135] Add support for MACROBUTTON Field (#1021) * add functionality to use MACROBUTTON as Field, use Styles for Field, add noProof to Font Style * code review * refactoring + fixes + unit tests --- CHANGELOG.md | 1 + samples/Sample_27_Field.php | 14 +++++ src/PhpWord/Element/Field.php | 52 ++++++++++++++++ src/PhpWord/Style/Font.php | 31 ++++++++++ src/PhpWord/Writer/Word2007/Element/Field.php | 60 ++++++++++++++++++- src/PhpWord/Writer/Word2007/Style/Font.php | 3 + tests/PhpWord/Writer/Word2007/ElementTest.php | 31 ++++++++++ 7 files changed, 191 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6f87158a6..c684a37d89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ v0.15.0 (?? ??? 2018) - Add support for fixed Table Layout @aoloe @ekopach @troosan #841 #1276 - Add support for Cell Spacing @dox07 @troosan #1040 - Add parsing of formatting inside lists @atomicalnet @troosan #594 +- Add support for MACROBUTTON field @phryneas @troosan #1021 ### Fixed - Fix reading of docx default style - @troosan #1238 diff --git a/samples/Sample_27_Field.php b/samples/Sample_27_Field.php index ec9dbe2537..9c37dffe91 100644 --- a/samples/Sample_27_Field.php +++ b/samples/Sample_27_Field.php @@ -20,6 +20,7 @@ $section->addText('Number of pages field:'); $section->addField('NUMPAGES', array('numformat' => '0,00', 'format' => 'Arabic'), array('PreserveFormat')); +$section->addTextBreak(); $textrun = $section->addTextRun(); $textrun->addText('An index field is '); @@ -43,6 +44,19 @@ $textrun->addText('This is the date of lunar calendar '); $textrun->addField('DATE', array('dateformat' => 'd-M-yyyy H:mm:ss'), array('PreserveFormat', 'LunarCalendar')); $textrun->addText(' written in a textrun.'); +$section->addTextBreak(); + +$macroText = new TextRun(); +$macroText->addText('Double click', array('bold' => true)); +$macroText->addText(' to '); +$macroText->addText('zoom to 100%', array('italic' => true)); + +$section->addText('A macro button with styled text:'); +$section->addField('MACROBUTTON', array('macroname' => 'Zoom100'), array(), $macroText); +$section->addTextBreak(); + +$section->addText('A macro button with simple text:'); +$section->addField('MACROBUTTON', array('macroname' => 'Zoom100'), array(), 'double click to zoom'); // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); diff --git a/src/PhpWord/Element/Field.php b/src/PhpWord/Element/Field.php index 7b33a4799d..5aeffbc168 100644 --- a/src/PhpWord/Element/Field.php +++ b/src/PhpWord/Element/Field.php @@ -17,6 +17,8 @@ namespace PhpOffice\PhpWord\Element; +use PhpOffice\PhpWord\Style\Font; + /** * Field element * @@ -54,6 +56,9 @@ class Field extends AbstractElement ), 'options' => array('PreserveFormat', 'LunarCalendar', 'SakaEraCalendar', 'LastUsedFormat'), ), + 'MACROBUTTON' => array( + 'properties' => array('macroname' => ''), + ), 'XE' => array( 'properties' => array(), 'options' => array('Bold', 'Italic'), @@ -92,6 +97,13 @@ class Field extends AbstractElement */ protected $options = array(); + /** + * Font style + * + * @var \PhpOffice\PhpWord\Style\Font + */ + protected $fontStyle; + /** * Create a new Field Element * @@ -203,6 +215,46 @@ public function getOptions() return $this->options; } + /** + * Set Text style + * + * @param \PhpOffice\PhpWord\Style\Font $style + * @return \PhpOffice\PhpWord\Style\Font + */ + public function setFontStyle($style = null) + { + if (!$style instanceof Font) { + throw new \InvalidArgumentException('font style must be of type Font'); + } + + if ($style->isNoProof()) { + $this->fontStyle = $style; + } else { + // make a copy of the font so the original is not altered + $this->fontStyle = clone $style; + $this->fontStyle->setNoProof(true); + } + + return $this->fontStyle; + } + + /** + * Get Text style + * + * @return \PhpOffice\PhpWord\Style\Font + */ + public function getFontStyle() + { + if ($this->fontStyle == null) { + $font = new Font(); + $font->setNoProof(true); + + return $font; + } + + return $this->fontStyle; + } + /** * Set Field text * diff --git a/src/PhpWord/Style/Font.php b/src/PhpWord/Style/Font.php index 8bfb3ac5d0..03fb692c97 100644 --- a/src/PhpWord/Style/Font.php +++ b/src/PhpWord/Style/Font.php @@ -236,6 +236,14 @@ class Font extends AbstractStyle */ private $rtl = false; + /** + * noProof (disables AutoCorrect) + * + * @var bool + * http://www.datypic.com/sc/ooxml/e-w_noProof-1.html + */ + private $noProof = false; + /** * Languages * @var \PhpOffice\PhpWord\Style\Language @@ -706,6 +714,29 @@ public function setKerning($value = null) return $this; } + /** + * Get noProof (disables autocorrect) + * + * @return bool + */ + public function isNoProof() + { + return $this->noProof; + } + + /** + * Set noProof (disables autocorrect) + * + * @param bool $value + * @return $this + */ + public function setNoProof($value = false) + { + $this->noProof = $value; + + return $this; + } + /** * Get line height * diff --git a/src/PhpWord/Writer/Word2007/Element/Field.php b/src/PhpWord/Writer/Word2007/Element/Field.php index 75d4983fef..336a432574 100644 --- a/src/PhpWord/Writer/Word2007/Element/Field.php +++ b/src/PhpWord/Writer/Word2007/Element/Field.php @@ -29,12 +29,22 @@ class Field extends Text */ public function write() { - $xmlWriter = $this->getXmlWriter(); $element = $this->getElement(); if (!$element instanceof \PhpOffice\PhpWord\Element\Field) { return; } + $methodName = 'write' . ucfirst(strtolower($element->getType())); + if (method_exists($this, $methodName)) { + $this->$methodName($element); + } else { + $this->writeDefault($element); + } + } + + private function writeDefault(\PhpOffice\PhpWord\Element\Field $element) + { + $xmlWriter = $this->getXmlWriter(); $this->startElementP(); $xmlWriter->startElement('w:r'); @@ -104,6 +114,51 @@ public function write() $this->endElementP(); // w:p } + /** + * Writes a macrobutton field + * + * //TODO A lot of code duplication with general method, should maybe be refactored + * @param \PhpOffice\PhpWord\Element\Field $element + */ + protected function writeMacrobutton(\PhpOffice\PhpWord\Element\Field $element) + { + $xmlWriter = $this->getXmlWriter(); + $this->startElementP(); + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:fldChar'); + $xmlWriter->writeAttribute('w:fldCharType', 'begin'); + $xmlWriter->endElement(); // w:fldChar + $xmlWriter->endElement(); // w:r + + $instruction = ' ' . $element->getType() . ' ' . $this->buildPropertiesAndOptions($element); + if (is_string($element->getText())) { + $instruction .= $element->getText() . ' '; + } + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:instrText'); + $xmlWriter->writeAttribute('xml:space', 'preserve'); + $xmlWriter->text($instruction); + $xmlWriter->endElement(); // w:instrText + $xmlWriter->endElement(); // w:r + + if ($element->getText() != null) { + if ($element->getText() instanceof \PhpOffice\PhpWord\Element\TextRun) { + $containerWriter = new Container($xmlWriter, $element->getText(), true); + $containerWriter->write(); + } + } + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:fldChar'); + $xmlWriter->writeAttribute('w:fldCharType', 'end'); + $xmlWriter->endElement(); // w:fldChar + $xmlWriter->endElement(); // w:r + + $this->endElementP(); // w:p + } + private function buildPropertiesAndOptions(\PhpOffice\PhpWord\Element\Field $element) { $propertiesAndOptions = ''; @@ -119,6 +174,9 @@ private function buildPropertiesAndOptions(\PhpOffice\PhpWord\Element\Field $ele case 'dateformat': $propertiesAndOptions .= '\@ "' . $propval . '" '; break; + case 'macroname': + $propertiesAndOptions .= $propval . ' '; + break; } } diff --git a/src/PhpWord/Writer/Word2007/Style/Font.php b/src/PhpWord/Writer/Word2007/Style/Font.php index ecaad416c6..a13db155db 100644 --- a/src/PhpWord/Writer/Word2007/Style/Font.php +++ b/src/PhpWord/Writer/Word2007/Style/Font.php @@ -135,6 +135,9 @@ private function writeStyle() $xmlWriter->writeElementIf($style->getSpacing() !== null, 'w:spacing', 'w:val', $style->getSpacing()); $xmlWriter->writeElementIf($style->getKerning() !== null, 'w:kern', 'w:val', $style->getKerning() * 2); + // noProof + $xmlWriter->writeElementIf($style->isNoProof() !== false, 'w:noProof'); + // Background-Color $shading = $style->getShading(); if (!is_null($shading)) { diff --git a/tests/PhpWord/Writer/Word2007/ElementTest.php b/tests/PhpWord/Writer/Word2007/ElementTest.php index f91a8479da..887e8e5881 100644 --- a/tests/PhpWord/Writer/Word2007/ElementTest.php +++ b/tests/PhpWord/Writer/Word2007/ElementTest.php @@ -322,6 +322,37 @@ public function testFieldElementWithComplexText() $this->assertEquals('"\\b \\i ', $doc->getElement($element)->textContent); } + /** + * Test writing the macrobutton field + */ + public function testMacroButtonField() + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + + $macroText = new TextRun(); + $macroText->addText('Double click', array('bold' => true)); + $macroText->addText(' to '); + $macroText->addText('zoom to 100%', array('italic' => true)); + + $section->addField('MACROBUTTON', array('macroname' => 'Zoom100'), array(), $macroText); + $section->addField('MACROBUTTON', array('macroname' => 'Zoom100'), array(), 'double click to zoom'); + $doc = TestHelperDOCX::getDocument($phpWord); + + $element = '/w:document/w:body/w:p[1]/w:r[2]/w:instrText'; + $this->assertTrue($doc->elementExists($element)); + $this->assertEquals(' MACROBUTTON Zoom100 ', $doc->getElement($element)->textContent); + + $element = '/w:document/w:body/w:p[1]/w:r[3]/'; + $this->assertTrue($doc->elementExists($element . 'w:t')); + $this->assertEquals('Double click', $doc->getElement($element . 'w:t')->textContent); + $this->assertTrue($doc->elementExists($element . 'w:rPr/w:b')); + + $element = '/w:document/w:body/w:p[2]/w:r[2]/w:instrText'; + $this->assertTrue($doc->elementExists($element)); + $this->assertEquals(' MACROBUTTON Zoom100 double click to zoom ', $doc->getElement($element)->textContent); + } + /** * Test form fields */ From 0869bdc8f78d584b6091a1dcdc5caf507e637cca Mon Sep 17 00:00:00 2001 From: Damjan Cvetko Date: Thu, 1 Mar 2018 01:24:59 +0100 Subject: [PATCH 042/135] Add support for reading element in runs. Internaly encoding it as "\t". --- src/PhpWord/Reader/Word2007/AbstractPart.php | 6 ++++-- tests/PhpWord/Reader/Word2007/ElementTest.php | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 1d61051652..70d3d96081 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -241,9 +241,11 @@ protected function readRun(XMLReader $xmlReader, \DOMElement $domNode, $parent, if ($xmlReader->elementExists('w:br', $domNode)) { $parent->addTextBreak(); } - if ($xmlReader->elementExists('w:t', $domNode)) { + if ($xmlReader->elementExists('w:t', $domNode) || $xmlReader->elementExists('w:tab', $domNode)) { // TextRun - if ($domNode->parentNode->nodeName == 'w:del') { + if ($xmlReader->elementExists('w:tab', $domNode)) { + $textContent = "\t"; + } elseif ($domNode->parentNode->nodeName == 'w:del') { $textContent = $xmlReader->getValue('w:delText', $domNode); } else { $textContent = $xmlReader->getValue('w:t', $domNode); diff --git a/tests/PhpWord/Reader/Word2007/ElementTest.php b/tests/PhpWord/Reader/Word2007/ElementTest.php index c2648b6839..6804b1724a 100644 --- a/tests/PhpWord/Reader/Word2007/ElementTest.php +++ b/tests/PhpWord/Reader/Word2007/ElementTest.php @@ -83,4 +83,22 @@ public function testReadListItemRunWithFormatting() $this->assertEquals('bold', $listElements[2]->getText()); $this->assertTrue($listElements[2]->getFontStyle()->getBold()); } + + /** + * Test reading of tab + */ + public function testReadTab() + { + $documentXml = ' + + + + '; + + $phpWord = $this->getDocumentFromString($documentXml); + + $elements = $this->get($phpWord->getSections(), 0)->getElements(); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $elements[0]); + $this->assertEquals("\t", $elements[0]->getText()); + } } From 740e66acf58394c47a991181184efc6d010f3a38 Mon Sep 17 00:00:00 2001 From: troosan Date: Fri, 2 Mar 2018 07:17:26 +0100 Subject: [PATCH 043/135] randomize the tempDir more to make sure directory is unique [ci skip] --- src/PhpWord/Writer/AbstractWriter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/Writer/AbstractWriter.php b/src/PhpWord/Writer/AbstractWriter.php index 538d9c0329..bb943d7ea5 100644 --- a/src/PhpWord/Writer/AbstractWriter.php +++ b/src/PhpWord/Writer/AbstractWriter.php @@ -216,7 +216,7 @@ public function setTempDir($value) protected function getTempFile($filename) { // Temporary directory - $this->setTempDir(Settings::getTempDir() . uniqid('/PHPWordWriter_') . '/'); + $this->setTempDir(Settings::getTempDir() . uniqid('/PHPWordWriter_', true) . '/'); // Temporary file $this->originalFilename = $filename; From 8a2cba22926242b6ec9433781b8878d301ae1e0e Mon Sep 17 00:00:00 2001 From: Damjan Cvetko Date: Sun, 4 Mar 2018 17:13:06 +0100 Subject: [PATCH 044/135] Support multiple elements (w:t, w:delText, w:tab) in w:r. --- src/PhpWord/Reader/Word2007/AbstractPart.php | 18 +++++++++++------- tests/PhpWord/Reader/Word2007/ElementTest.php | 4 +++- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 70d3d96081..c69f636a99 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -241,14 +241,18 @@ protected function readRun(XMLReader $xmlReader, \DOMElement $domNode, $parent, if ($xmlReader->elementExists('w:br', $domNode)) { $parent->addTextBreak(); } - if ($xmlReader->elementExists('w:t', $domNode) || $xmlReader->elementExists('w:tab', $domNode)) { + if ($xmlReader->elementExists('w:t', $domNode) || $xmlReader->elementExists('w:tab', $domNode) || $xmlReader->elementExists('w:delText', $domNode)) { // TextRun - if ($xmlReader->elementExists('w:tab', $domNode)) { - $textContent = "\t"; - } elseif ($domNode->parentNode->nodeName == 'w:del') { - $textContent = $xmlReader->getValue('w:delText', $domNode); - } else { - $textContent = $xmlReader->getValue('w:t', $domNode); + $textContent = ''; + $nodes = $xmlReader->getElements('w:t|w:delText|w:tab', $domNode); + foreach ($nodes as $node) { + if ($node->nodeName == 'w:t') { + $textContent .= $node->nodeValue; + } elseif ($node->nodeName == 'w:delText') { + $textContent .= $node->nodeValue; + } elseif ($node->nodeName == 'w:tab') { + $textContent .= "\t"; + } } /** @var AbstractElement $element */ $element = $parent->addText($textContent, $fontStyle, $paragraphStyle); diff --git a/tests/PhpWord/Reader/Word2007/ElementTest.php b/tests/PhpWord/Reader/Word2007/ElementTest.php index 6804b1724a..aad4a5436a 100644 --- a/tests/PhpWord/Reader/Word2007/ElementTest.php +++ b/tests/PhpWord/Reader/Word2007/ElementTest.php @@ -91,7 +91,9 @@ public function testReadTab() { $documentXml = ' + One + Two '; @@ -99,6 +101,6 @@ public function testReadTab() $elements = $this->get($phpWord->getSections(), 0)->getElements(); $this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $elements[0]); - $this->assertEquals("\t", $elements[0]->getText()); + $this->assertEquals("One\tTwo", $elements[0]->getText()); } } From 30b224b3d099f417507c422c1244e6174dbee4d0 Mon Sep 17 00:00:00 2001 From: troosan Date: Tue, 6 Mar 2018 06:34:55 +0100 Subject: [PATCH 045/135] Word2007 parsing title formatting (#1297) * Improve Title parsing - Title should be able to contain TextRun - Style 'Title' should be treated the same with as Heading - Add tests for Heading/Title reader * update the documentation and the changelog * PHP 7.2 build should not fail anymore * reduce dependencies versions * fix parsing of footnotes and endnotes * add method to remove an element from a section --- .scrutinizer.yml | 5 + .travis.yml | 5 +- CHANGELOG.md | 1 + docs/elements.rst | 3 +- samples/Sample_17_TitleTOC.php | 3 +- src/PhpWord/Collection/AbstractCollection.php | 10 +- src/PhpWord/Element/AbstractContainer.php | 37 +++- src/PhpWord/Element/Bookmark.php | 2 +- src/PhpWord/Element/ListItem.php | 2 +- src/PhpWord/Element/Title.php | 20 ++- src/PhpWord/PhpWord.php | 15 ++ src/PhpWord/Reader/Word2007/AbstractPart.php | 61 +++++-- src/PhpWord/Reader/Word2007/Footnotes.php | 43 +++-- src/PhpWord/Style.php | 8 +- src/PhpWord/Writer/Word2007/Element/Title.php | 45 +++-- src/PhpWord/Writer/Word2007/Part/Styles.php | 12 +- tests/PhpWord/Element/SectionTest.php | 31 ++++ tests/PhpWord/Element/TitleTest.php | 21 +++ tests/PhpWord/Reader/Word2007/ElementTest.php | 70 +++++++- tests/PhpWord/Reader/Word2007/PartTest.php | 163 ++++++++++++++++++ tests/PhpWord/Reader/Word2007/StyleTest.php | 8 +- tests/PhpWord/Writer/Word2007/ElementTest.php | 29 ++++ .../Writer/Word2007/Part/DocumentTest.php | 1 - .../PhpWord/_includes/AbstractTestReader.php | 43 +++-- 24 files changed, 539 insertions(+), 99 deletions(-) create mode 100644 tests/PhpWord/Reader/Word2007/PartTest.php diff --git a/.scrutinizer.yml b/.scrutinizer.yml index c8fe57cf63..291a6d60cd 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -1,3 +1,8 @@ +build: + nodes: + analysis: + tests: + override: [php-scrutinizer-run] filter: excluded_paths: [ 'vendor/*', 'tests/*', 'samples/*', 'src/PhpWord/Shared/PCLZip/*' ] diff --git a/.travis.yml b/.travis.yml index d63b7bb22c..281c263098 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,12 +15,9 @@ matrix: include: - php: 5.6 env: COVERAGE=1 - allow_failures: - - php: 7.2 cache: directories: - - vendor - $HOME/.composer/cache - .php-cs.cache @@ -38,7 +35,7 @@ before_script: - if [ -z "$COVERAGE" ]; then phpenv config-rm xdebug.ini ; fi ## Composer - composer self-update - - composer install --prefer-source + - travis_wait composer install --prefer-source ## PHPDocumentor - mkdir -p build/docs - mkdir -p build/coverage diff --git a/CHANGELOG.md b/CHANGELOG.md index c684a37d89..7f527746f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ v0.15.0 (?? ??? 2018) - Fix parsing of `` tag. @troosan #1274 - Bookmark are not writton as internal link in html writer @troosan #1263 - It should be possible to add a Footnote in a ListItemRun @troosan #1287 #1287 +- Fix parsing of Heading and Title formating @troosan @gthomas2 #465 ### Changed - Remove zend-stdlib dependency @Trainmaster #1284 diff --git a/docs/elements.rst b/docs/elements.rst index d13abc5634..4d1b93838c 100644 --- a/docs/elements.rst +++ b/docs/elements.rst @@ -89,6 +89,7 @@ Titles If you want to structure your document or build table of contents, you need titles or headings. To add a title to the document, use the ``addTitleStyle`` and ``addTitle`` method. +If `depth` is 0, a Title will be inserted, otherwise a Heading1, Heading2, ... .. code-block:: php @@ -98,7 +99,7 @@ To add a title to the document, use the ``addTitleStyle`` and ``addTitle`` metho - ``depth``. - ``$fontStyle``. See :ref:`font-style`. - ``$paragraphStyle``. See :ref:`paragraph-style`. -- ``$text``. Text to be displayed in the document. +- ``$text``. Text to be displayed in the document. This can be `string` or a `\PhpOffice\PhpWord\Element\TextRun` It's necessary to add a title style to your document because otherwise the title won't be detected as a real title. diff --git a/samples/Sample_17_TitleTOC.php b/samples/Sample_17_TitleTOC.php index f99b73ea86..86e8e28cf7 100644 --- a/samples/Sample_17_TitleTOC.php +++ b/samples/Sample_17_TitleTOC.php @@ -12,13 +12,14 @@ // Define styles $fontStyle12 = array('spaceAfter' => 60, 'size' => 12); $fontStyle10 = array('size' => 10); +$phpWord->addTitleStyle(null, array('size' => 22, 'bold' => true)); $phpWord->addTitleStyle(1, array('size' => 20, 'color' => '333333', 'bold' => true)); $phpWord->addTitleStyle(2, array('size' => 16, 'color' => '666666')); $phpWord->addTitleStyle(3, array('size' => 14, 'italic' => true)); $phpWord->addTitleStyle(4, array('size' => 12)); // Add text elements -$section->addText('Table of contents 1'); +$section->addTitle('Table of contents 1', 0); $section->addTextBreak(2); // Add TOC #1 diff --git a/src/PhpWord/Collection/AbstractCollection.php b/src/PhpWord/Collection/AbstractCollection.php index 61709a5001..d49967cac7 100644 --- a/src/PhpWord/Collection/AbstractCollection.php +++ b/src/PhpWord/Collection/AbstractCollection.php @@ -27,14 +27,14 @@ abstract class AbstractCollection /** * Items * - * @var array + * @var \PhpOffice\PhpWord\Element\AbstractContainer[] */ private $items = array(); /** * Get items * - * @return array + * @return \PhpOffice\PhpWord\Element\AbstractContainer[] */ public function getItems() { @@ -45,7 +45,7 @@ public function getItems() * Get item by index * * @param int $index - * @return mixed + * @return \PhpOffice\PhpWord\Element\AbstractContainer */ public function getItem($index) { @@ -60,7 +60,7 @@ public function getItem($index) * Set item. * * @param int $index - * @param mixed $item + * @param \PhpOffice\PhpWord\Element\AbstractContainer $item */ public function setItem($index, $item) { @@ -72,7 +72,7 @@ public function setItem($index, $item) /** * Add new item * - * @param mixed $item + * @param \PhpOffice\PhpWord\Element\AbstractContainer $item * @return int */ public function addItem($item) diff --git a/src/PhpWord/Element/AbstractContainer.php b/src/PhpWord/Element/AbstractContainer.php index 507ff143e5..1cedbef01f 100644 --- a/src/PhpWord/Element/AbstractContainer.php +++ b/src/PhpWord/Element/AbstractContainer.php @@ -54,7 +54,7 @@ abstract class AbstractContainer extends AbstractElement /** * Elements collection * - * @var array + * @var \PhpOffice\PhpWord\Element\AbstractElement[] */ protected $elements = array(); @@ -164,6 +164,41 @@ public function getElements() return $this->elements; } + /** + * Returns the element at the requested position + * + * @param int $index + * @return \PhpOffice\PhpWord\Element\AbstractElement|null + */ + public function getElement($index) + { + if (array_key_exists($index, $this->elements)) { + return $this->elements[$index]; + } + + return null; + } + + /** + * Removes the element at requested index + * + * @param int|\PhpOffice\PhpWord\Element\AbstractElement $toRemove + */ + public function removeElement($toRemove) + { + if (is_int($toRemove) && array_key_exists($toRemove, $this->elements)) { + unset($this->elements[$toRemove]); + } elseif ($toRemove instanceof \PhpOffice\PhpWord\Element\AbstractElement) { + foreach ($this->elements as $key => $element) { + if ($element->getElementId() === $toRemove->getElementId()) { + unset($this->elements[$key]); + + return; + } + } + } + } + /** * Count elements * diff --git a/src/PhpWord/Element/Bookmark.php b/src/PhpWord/Element/Bookmark.php index 2eceb5ed89..8d4e0af53e 100644 --- a/src/PhpWord/Element/Bookmark.php +++ b/src/PhpWord/Element/Bookmark.php @@ -43,7 +43,7 @@ class Bookmark extends AbstractElement * * @param string $name */ - public function __construct($name) + public function __construct($name = '') { $this->name = CommonText::toUTF8($name); } diff --git a/src/PhpWord/Element/ListItem.php b/src/PhpWord/Element/ListItem.php index 7f665b1b9f..cb55c5ae86 100644 --- a/src/PhpWord/Element/ListItem.php +++ b/src/PhpWord/Element/ListItem.php @@ -62,7 +62,7 @@ public function __construct($text, $depth = 0, $fontStyle = null, $listStyle = n // Version >= 0.10.0 will pass numbering style name. Older version will use old method if (!is_null($listStyle) && is_string($listStyle)) { - $this->style = new ListItemStyle($listStyle); + $this->style = new ListItemStyle($listStyle); // @codeCoverageIgnore } else { $this->style = $this->setNewStyle(new ListItemStyle(), $listStyle, true); } diff --git a/src/PhpWord/Element/Title.php b/src/PhpWord/Element/Title.php index 808af55ebb..ed06fa1342 100644 --- a/src/PhpWord/Element/Title.php +++ b/src/PhpWord/Element/Title.php @@ -28,7 +28,7 @@ class Title extends AbstractElement /** * Title Text content * - * @var string + * @var string|TextRun */ private $text; @@ -56,15 +56,25 @@ class Title extends AbstractElement /** * Create a new Title Element * - * @param string $text + * @param string|TextRun $text * @param int $depth */ public function __construct($text, $depth = 1) { - $this->text = CommonText::toUTF8($text); + if (isset($text)) { + if (is_string($text)) { + $this->text = CommonText::toUTF8($text); + } elseif ($text instanceof TextRun) { + $this->text = $text; + } else { + throw new \InvalidArgumentException('Invalid text, should be a string or a TextRun'); + } + } + $this->depth = $depth; - if (array_key_exists("Heading_{$this->depth}", Style::getStyles())) { - $this->style = "Heading{$this->depth}"; + $styleName = $depth === 0 ? 'Title' : "Heading_{$this->depth}"; + if (array_key_exists($styleName, Style::getStyles())) { + $this->style = str_replace('_', '', $styleName); } return $this; diff --git a/src/PhpWord/PhpWord.php b/src/PhpWord/PhpWord.php index d7c2348a63..54ef65ac97 100644 --- a/src/PhpWord/PhpWord.php +++ b/src/PhpWord/PhpWord.php @@ -212,6 +212,21 @@ public function getSections() return $this->sections; } + /** + * Returns the section at the requested position + * + * @param int $index + * @return \PhpOffice\PhpWord\Element\Section|null + */ + public function getSection($index) + { + if (array_key_exists($index, $this->sections)) { + return $this->sections[$index]; + } + + return null; + } + /** * Create new section * diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 1d61051652..f8a26ddb2e 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -18,6 +18,7 @@ namespace PhpOffice\PhpWord\Reader\Word2007; use PhpOffice\Common\XMLReader; +use PhpOffice\PhpWord\Element\TextRun; use PhpOffice\PhpWord\Element\TrackChange; use PhpOffice\PhpWord\PhpWord; @@ -103,12 +104,10 @@ protected function readParagraph(XMLReader $xmlReader, \DOMElement $domNode, $pa { // Paragraph style $paragraphStyle = null; - $headingMatches = array(); + $headingDepth = null; if ($xmlReader->elementExists('w:pPr', $domNode)) { $paragraphStyle = $this->readParagraphStyle($xmlReader, $domNode); - if (is_array($paragraphStyle) && isset($paragraphStyle['styleName'])) { - preg_match('/Heading(\d)/', $paragraphStyle['styleName'], $headingMatches); - } + $headingDepth = $this->getHeadingDepth($paragraphStyle); } // PreserveText @@ -147,14 +146,19 @@ protected function readParagraph(XMLReader $xmlReader, \DOMElement $domNode, $pa foreach ($nodes as $node) { $this->readRun($xmlReader, $node, $listItemRun, $docPart, $paragraphStyle); } - } elseif (!empty($headingMatches)) { - // Heading - $textContent = ''; + } elseif ($headingDepth !== null) { + // Heading or Title + $textContent = null; $nodes = $xmlReader->getElements('w:r', $domNode); - foreach ($nodes as $node) { - $textContent .= $xmlReader->getValue('w:t', $node); + if ($nodes->length === 1) { + $textContent = $xmlReader->getValue('w:t', $nodes->item(0)); + } else { + $textContent = new TextRun($paragraphStyle); + foreach ($nodes as $node) { + $this->readRun($xmlReader, $node, $textContent, $docPart, $paragraphStyle); + } } - $parent->addTitle($textContent, $headingMatches[1]); + $parent->addTitle($textContent, $headingDepth); } else { // Text and TextRun $runCount = $xmlReader->countElements('w:r', $domNode); @@ -176,6 +180,29 @@ protected function readParagraph(XMLReader $xmlReader, \DOMElement $domNode, $pa } } + /** + * Returns the depth of the Heading, returns 0 for a Title + * + * @param array $paragraphStyle + * @return number|null + */ + private function getHeadingDepth(array $paragraphStyle = null) + { + if (is_array($paragraphStyle) && isset($paragraphStyle['styleName'])) { + if ('Title' === $paragraphStyle['styleName']) { + return 0; + } + + $headingMatches = array(); + preg_match('/Heading(\d)/', $paragraphStyle['styleName'], $headingMatches); + if (!empty($headingMatches)) { + return $headingMatches[1]; + } + } + + return null; + } + /** * Read w:r. * @@ -212,10 +239,14 @@ protected function readRun(XMLReader $xmlReader, \DOMElement $domNode, $parent, } else { if ($xmlReader->elementExists('w:footnoteReference', $domNode)) { // Footnote - $parent->addFootnote(); + $wId = $xmlReader->getAttribute('w:id', $domNode, 'w:footnoteReference'); + $footnote = $parent->addFootnote(); + $footnote->setRelationId($wId); } elseif ($xmlReader->elementExists('w:endnoteReference', $domNode)) { // Endnote - $parent->addEndnote(); + $wId = $xmlReader->getAttribute('w:id', $domNode, 'w:endnoteReference'); + $endnote = $parent->addEndnote(); + $endnote->setRelationId($wId); } elseif ($xmlReader->elementExists('w:pict', $domNode)) { // Image $rId = $xmlReader->getAttribute('r:id', $domNode, 'w:pict/v:shape/v:imagedata'); @@ -496,11 +527,9 @@ private function findPossibleAttribute(XMLReader $xmlReader, \DOMElement $node, return $possibleAttribute; } } - } else { - return $attributes; } - return null; + return $attributes; } /** @@ -578,7 +607,7 @@ private function readStyleDef($method, $attributeValue, $expected) */ private function isOn($value = null) { - return $value == null || $value == '1' || $value == 'true' || $value == 'on'; + return $value === null || $value === '1' || $value === 'true' || $value === 'on'; } /** diff --git a/src/PhpWord/Reader/Word2007/Footnotes.php b/src/PhpWord/Reader/Word2007/Footnotes.php index 61988723d9..b69b26061c 100644 --- a/src/PhpWord/Reader/Word2007/Footnotes.php +++ b/src/PhpWord/Reader/Word2007/Footnotes.php @@ -48,9 +48,6 @@ class Footnotes extends AbstractPart */ public function read(PhpWord $phpWord) { - $getMethod = "get{$this->collection}"; - $collection = $phpWord->$getMethod()->getItems(); - $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($this->docFile, $this->xmlFile); $nodes = $xmlReader->getElements('*'); @@ -60,17 +57,41 @@ public function read(PhpWord $phpWord) $type = $xmlReader->getAttribute('w:type', $node); // Avoid w:type "separator" and "continuationSeparator" - // Only look for or without w:type attribute - if (is_null($type) && isset($collection[$id])) { - $element = $collection[$id]; - $pNodes = $xmlReader->getElements('w:p/*', $node); - foreach ($pNodes as $pNode) { - $this->readRun($xmlReader, $pNode, $element, $this->collection); + // Only look for or without w:type attribute, or with w:type = normal + if ((is_null($type) || $type === 'normal')) { + $element = $this->getElement($phpWord, $id); + if ($element !== null) { + $pNodes = $xmlReader->getElements('w:p/*', $node); + foreach ($pNodes as $pNode) { + $this->readRun($xmlReader, $pNode, $element, $this->collection); + } + $addMethod = "add{$this->element}"; + $phpWord->$addMethod($element); } - $addMethod = "add{$this->element}"; - $phpWord->$addMethod($element); } } } } + + /** + * Searches for the element with the given relationId + * + * @param PhpWord $phpWord + * @param int $relationId + * @return \PhpOffice\PhpWord\Element\AbstractContainer|null + */ + private function getElement(PhpWord $phpWord, $relationId) + { + $getMethod = "get{$this->collection}"; + $collection = $phpWord->$getMethod()->getItems(); + + //not found by key, looping to search by relationId + foreach ($collection as $collectionElement) { + if ($collectionElement->getRelationId() == $relationId) { + return $collectionElement; + } + } + + return null; + } } diff --git a/src/PhpWord/Style.php b/src/PhpWord/Style.php index 1939aabac6..017b329003 100644 --- a/src/PhpWord/Style.php +++ b/src/PhpWord/Style.php @@ -95,7 +95,13 @@ public static function addNumberingStyle($styleName, $styleValues) */ public static function addTitleStyle($depth, $fontStyle, $paragraphStyle = null) { - return self::setStyleValues("Heading_{$depth}", new Font('title', $paragraphStyle), $fontStyle); + if ($depth == null) { + $styleName = 'Title'; + } else { + $styleName = "Heading_{$depth}"; + } + + return self::setStyleValues($styleName, new Font('title', $paragraphStyle), $fontStyle); } /** diff --git a/src/PhpWord/Writer/Word2007/Element/Title.php b/src/PhpWord/Writer/Word2007/Element/Title.php index f204ab1617..80c0904d6a 100644 --- a/src/PhpWord/Writer/Word2007/Element/Title.php +++ b/src/PhpWord/Writer/Word2007/Element/Title.php @@ -47,27 +47,36 @@ public function write() $xmlWriter->endElement(); } - $rId = $element->getRelationId(); - $bookmarkRId = $element->getPhpWord()->addBookmark(); + if ($element->getDepth() !== 0) { + $rId = $element->getRelationId(); + $bookmarkRId = $element->getPhpWord()->addBookmark(); - // Bookmark start for TOC - $xmlWriter->startElement('w:bookmarkStart'); - $xmlWriter->writeAttribute('w:id', $bookmarkRId); - $xmlWriter->writeAttribute('w:name', "_Toc{$rId}"); - $xmlWriter->endElement(); + // Bookmark start for TOC + $xmlWriter->startElement('w:bookmarkStart'); + $xmlWriter->writeAttribute('w:id', $bookmarkRId); + $xmlWriter->writeAttribute('w:name', "_Toc{$rId}"); + $xmlWriter->endElement(); //w:bookmarkStart + } // Actual text - $xmlWriter->startElement('w:r'); - $xmlWriter->startElement('w:t'); - $this->writeText($this->getText($element->getText())); - $xmlWriter->endElement(); // w:t - $xmlWriter->endElement(); // w:r - - // Bookmark end - $xmlWriter->startElement('w:bookmarkEnd'); - $xmlWriter->writeAttribute('w:id', $bookmarkRId); - $xmlWriter->endElement(); + $text = $element->getText(); + if (is_string($text)) { + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:t'); + $this->writeText($text); + $xmlWriter->endElement(); // w:t + $xmlWriter->endElement(); // w:r + } elseif ($text instanceof \PhpOffice\PhpWord\Element\AbstractContainer) { + $containerWriter = new Container($xmlWriter, $text); + $containerWriter->write(); + } - $xmlWriter->endElement(); + if ($element->getDepth() !== 0) { + // Bookmark end + $xmlWriter->startElement('w:bookmarkEnd'); + $xmlWriter->writeAttribute('w:id', $bookmarkRId); + $xmlWriter->endElement(); //w:bookmarkEnd + } + $xmlWriter->endElement(); //w:p } } diff --git a/src/PhpWord/Writer/Word2007/Part/Styles.php b/src/PhpWord/Writer/Word2007/Part/Styles.php index 1cc948065b..03855f03c0 100644 --- a/src/PhpWord/Writer/Word2007/Part/Styles.php +++ b/src/PhpWord/Writer/Word2007/Part/Styles.php @@ -180,9 +180,15 @@ private function writeFontStyle(XMLWriter $xmlWriter, $styleName, FontStyle $sty // Heading style if ($styleType == 'title') { $arrStyle = explode('_', $styleName); - $styleId = 'Heading' . $arrStyle[1]; - $styleName = 'heading ' . $arrStyle[1]; - $styleLink = 'Heading' . $arrStyle[1] . 'Char'; + if (count($arrStyle) > 1) { + $styleId = 'Heading' . $arrStyle[1]; + $styleName = 'heading ' . $arrStyle[1]; + $styleLink = 'Heading' . $arrStyle[1] . 'Char'; + } else { + $styleId = $styleName; + $styleName = strtolower($styleName); + $styleLink = $styleName . 'Char'; + } $xmlWriter->writeAttribute('w:styleId', $styleId); $xmlWriter->startElement('w:link'); diff --git a/tests/PhpWord/Element/SectionTest.php b/tests/PhpWord/Element/SectionTest.php index 20f0f0f759..867f680aeb 100644 --- a/tests/PhpWord/Element/SectionTest.php +++ b/tests/PhpWord/Element/SectionTest.php @@ -162,4 +162,35 @@ public function testAddHeaderException() $object = new Section(1); $object->addHeader('ODD'); } + + /** + * @covers \PhpOffice\PhpWord\Element\AbstractContainer::removeElement + */ + public function testRemoveElementByIndex() + { + $section = new Section(1); + $section->addText('firstText'); + $section->addText('secondText'); + + $this->assertEquals(2, $section->countElements()); + $section->removeElement(1); + + $this->assertEquals(1, $section->countElements()); + } + + /** + * @covers \PhpOffice\PhpWord\Element\AbstractContainer::removeElement + */ + public function testRemoveElementByElement() + { + $section = new Section(1); + $fistText = $section->addText('firstText'); + $secondText = $section->addText('secondText'); + + $this->assertEquals(2, $section->countElements()); + $section->removeElement($fistText); + + $this->assertEquals(1, $section->countElements()); + $this->assertEquals($secondText->getElementId(), $section->getElement(1)->getElementId()); + } } diff --git a/tests/PhpWord/Element/TitleTest.php b/tests/PhpWord/Element/TitleTest.php index 3ea6242f42..e99a80a63d 100644 --- a/tests/PhpWord/Element/TitleTest.php +++ b/tests/PhpWord/Element/TitleTest.php @@ -45,4 +45,25 @@ public function testStyleNull() $this->assertNull($oTitle->getStyle()); } + + /** + * Create new instance with TextRun + */ + public function testConstructWithTextRun() + { + $oTextRun = new TextRun(); + $oTextRun->addText('text'); + $oTitle = new Title($oTextRun); + + $this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\TextRun', $oTitle->getText()); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testConstructWithInvalidArgument() + { + $oPageBreak = new PageBreak(); + new Title($oPageBreak); + } } diff --git a/tests/PhpWord/Reader/Word2007/ElementTest.php b/tests/PhpWord/Reader/Word2007/ElementTest.php index c2648b6839..10c1ec9a15 100644 --- a/tests/PhpWord/Reader/Word2007/ElementTest.php +++ b/tests/PhpWord/Reader/Word2007/ElementTest.php @@ -36,9 +36,9 @@ public function testReadTextBreak() '; - $phpWord = $this->getDocumentFromString($documentXml); + $phpWord = $this->getDocumentFromString(array('document' => $documentXml)); - $elements = $this->get($phpWord->getSections(), 0)->getElements(); + $elements = $phpWord->getSection(0)->getElements(); $this->assertInstanceOf('PhpOffice\PhpWord\Element\TextBreak', $elements[0]); $this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $elements[1]); $this->assertEquals('test string', $elements[1]->getText()); @@ -70,17 +70,73 @@ public function testReadListItemRunWithFormatting() '; - $phpWord = $this->getDocumentFromString($documentXml); + $phpWord = $this->getDocumentFromString(array('document' => $documentXml)); - $elements = $this->get($phpWord->getSections(), 0)->getElements(); - $this->assertInstanceOf('PhpOffice\PhpWord\Element\ListItemRun', $elements[0]); - $this->assertEquals(0, $elements[0]->getDepth()); + $sections = $phpWord->getSection(0); + $this->assertNull($sections->getElement(999)); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\ListItemRun', $sections->getElement(0)); + $this->assertEquals(0, $sections->getElement(0)->getDepth()); - $listElements = $this->get($elements, 0)->getElements(); + $listElements = $sections->getElement(0)->getElements(); $this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $listElements[0]); $this->assertEquals('Two', $listElements[0]->getText()); $this->assertEquals(' with ', $listElements[1]->getText()); $this->assertEquals('bold', $listElements[2]->getText()); $this->assertTrue($listElements[2]->getFontStyle()->getBold()); } + + /** + * Test reading Title style + */ + public function testReadTitleStyle() + { + $documentXml = ' + + + + + This is a non formatted title + + + + + + + + This is a + + + + + + bold + + + title + + '; + + $stylesXml = ' + + + + + + '; + + $phpWord = $this->getDocumentFromString(array('document' => $documentXml, 'styles' => $stylesXml)); + + $elements = $phpWord->getSection(0)->getElements(); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\Title', $elements[0]); + /** @var \PhpOffice\PhpWord\Element\Title $title */ + $title = $elements[0]; + $this->assertEquals('Title', $title->getStyle()); + $this->assertEquals('This is a non formatted title', $title->getText()); + + $this->assertInstanceOf('PhpOffice\PhpWord\Element\Title', $elements[1]); + /** @var \PhpOffice\PhpWord\Element\Title $formattedTitle */ + $formattedTitle = $elements[1]; + $this->assertEquals('Title', $formattedTitle->getStyle()); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $formattedTitle->getText()); + } } diff --git a/tests/PhpWord/Reader/Word2007/PartTest.php b/tests/PhpWord/Reader/Word2007/PartTest.php new file mode 100644 index 0000000000..0f7ecc7c90 --- /dev/null +++ b/tests/PhpWord/Reader/Word2007/PartTest.php @@ -0,0 +1,163 @@ + + + This is a test + + + + + + + + + + + And another one + + + + + + + + '; + + $footnotesXml = ' + + + + + + + + + + + + + + + + + + + + + + footnote text + + + '; + + $endnotesXml = ' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is an endnote + + + '; + + $phpWord = $this->getDocumentFromString(array('document' => $documentXml, 'footnotes' => $footnotesXml, 'endnotes' => $endnotesXml)); + + $elements = $phpWord->getSection(0)->getElements(); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $elements[0]); + /** @var \PhpOffice\PhpWord\Element\TextRun $textRun */ + $textRun = $elements[0]; + + //test the text in the first paragraph + /** @var \PhpOffice\PhpWord\Element\Text $text */ + $text = $elements[0]->getElement(0); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $text); + $this->assertEquals('This is a test', $text->getText()); + + //test the presence of the footnote in the document.xml + /** @var \PhpOffice\PhpWord\Element\Footnote $footnote */ + $documentFootnote = $textRun->getElement(1); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\Footnote', $documentFootnote); + $this->assertEquals(1, $documentFootnote->getRelationId()); + + //test the presence of the footnote in the footnote.xml + /** @var \PhpOffice\PhpWord\Element\Footnote $footnote */ + $footnote = $phpWord->getFootnotes()->getItem(1); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\Footnote', $footnote); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $footnote->getElement(0)); + $this->assertEquals('footnote text', $footnote->getElement(0)->getText()); + $this->assertEquals(1, $footnote->getRelationId()); + + //test the text in the second paragraph + /** @var \PhpOffice\PhpWord\Element\Text $text */ + $text = $elements[1]->getElement(0); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $text); + $this->assertEquals('And another one', $text->getText()); + + //test the presence of the endnote in the document.xml + /** @var \PhpOffice\PhpWord\Element\Endnote $endnote */ + $documentEndnote = $elements[1]->getElement(1); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\Endnote', $documentEndnote); + $this->assertEquals(2, $documentEndnote->getRelationId()); + + //test the presence of the endnote in the endnote.xml + /** @var \PhpOffice\PhpWord\Element\Endnote $endnote */ + $endnote = $phpWord->getEndnotes()->getItem(1); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\Endnote', $endnote); + $this->assertEquals(2, $endnote->getRelationId()); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $endnote->getElement(0)); + $this->assertEquals('This is an endnote', $endnote->getElement(0)->getText()); + } +} diff --git a/tests/PhpWord/Reader/Word2007/StyleTest.php b/tests/PhpWord/Reader/Word2007/StyleTest.php index 4375df475a..c0d5d864d1 100644 --- a/tests/PhpWord/Reader/Word2007/StyleTest.php +++ b/tests/PhpWord/Reader/Word2007/StyleTest.php @@ -37,9 +37,9 @@ public function testReadTableLayout() '; - $phpWord = $this->getDocumentFromString($documentXml); + $phpWord = $this->getDocumentFromString(array('document' => $documentXml)); - $elements = $this->get($phpWord->getSections(), 0)->getElements(); + $elements = $phpWord->getSection(0)->getElements(); $this->assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]); $this->assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle()); $this->assertEquals(Table::LAYOUT_FIXED, $elements[0]->getStyle()->getLayout()); @@ -56,9 +56,9 @@ public function testReadCellSpacing() '; - $phpWord = $this->getDocumentFromString($documentXml); + $phpWord = $this->getDocumentFromString(array('document' => $documentXml)); - $elements = $this->get($phpWord->getSections(), 0)->getElements(); + $elements = $phpWord->getSection(0)->getElements(); $this->assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]); $this->assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle()); $this->assertEquals(TblWidth::AUTO, $elements[0]->getStyle()->getUnit()); diff --git a/tests/PhpWord/Writer/Word2007/ElementTest.php b/tests/PhpWord/Writer/Word2007/ElementTest.php index 887e8e5881..b59e369f5d 100644 --- a/tests/PhpWord/Writer/Word2007/ElementTest.php +++ b/tests/PhpWord/Writer/Word2007/ElementTest.php @@ -447,6 +447,9 @@ public function testCommentWithEndElement() $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:commentReference')); } + /** + * Test Track changes + */ public function testTrackChange() { $phpWord = new PhpWord(); @@ -462,4 +465,30 @@ public function testTrackChange() $this->assertEquals('author name', $doc->getElementAttribute('/w:document/w:body/w:p/w:ins', 'w:author')); $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:del/w:r/w:delText')); } + + /** + * Test Title and Headings + */ + public function testTitleAndHeading() + { + $phpWord = new PhpWord(); + $phpWord->addTitleStyle(0, array('size' => 14, 'italic' => true)); + $phpWord->addTitleStyle(1, array('size' => 20, 'color' => '333333', 'bold' => true)); + + $section = $phpWord->addSection(); + $section->addTitle('This is a title', 0); + $section->addTitle('Heading 1', 1); + + $doc = TestHelperDOCX::getDocument($phpWord); + + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:r/w:t')); + $this->assertEquals('This is a title', $doc->getElement('/w:document/w:body/w:p[1]/w:r/w:t')->textContent); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:pPr/w:pStyle')); + $this->assertEquals('Title', $doc->getElementAttribute('/w:document/w:body/w:p[1]/w:pPr/w:pStyle', 'w:val')); + + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p[2]/w:r/w:t')); + $this->assertEquals('Heading 1', $doc->getElement('/w:document/w:body/w:p[2]/w:r/w:t')->textContent); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p[2]/w:pPr/w:pStyle')); + $this->assertEquals('Heading1', $doc->getElementAttribute('/w:document/w:body/w:p[2]/w:pPr/w:pStyle', 'w:val')); + } } diff --git a/tests/PhpWord/Writer/Word2007/Part/DocumentTest.php b/tests/PhpWord/Writer/Word2007/Part/DocumentTest.php index 6998e717ee..39db602885 100644 --- a/tests/PhpWord/Writer/Word2007/Part/DocumentTest.php +++ b/tests/PhpWord/Writer/Word2007/Part/DocumentTest.php @@ -24,7 +24,6 @@ use PhpOffice\PhpWord\SimpleType\NumberFormat; use PhpOffice\PhpWord\Style\Cell; use PhpOffice\PhpWord\Style\Font; -use PhpOffice\PhpWord\Style\Paragraph; use PhpOffice\PhpWord\TestHelperDOCX; /** diff --git a/tests/PhpWord/_includes/AbstractTestReader.php b/tests/PhpWord/_includes/AbstractTestReader.php index f138ac76d0..348cab98af 100644 --- a/tests/PhpWord/_includes/AbstractTestReader.php +++ b/tests/PhpWord/_includes/AbstractTestReader.php @@ -17,43 +17,48 @@ namespace PhpOffice\PhpWord; -use PhpOffice\PhpWord\Reader\Word2007\Document; - /** * Base class for Word2007 reader tests */ abstract class AbstractTestReader extends \PHPUnit\Framework\TestCase { + private $parts = array( + 'styles' => array('class' => 'PhpOffice\PhpWord\Reader\Word2007\Styles', 'xml' => '{toReplace}'), + 'document' => array('class' => 'PhpOffice\PhpWord\Reader\Word2007\Document', 'xml' => '{toReplace}'), + 'footnotes' => array('class' => 'PhpOffice\PhpWord\Reader\Word2007\Footnotes', 'xml' => '{toReplace}'), + 'endnotes' => array('class' => 'PhpOffice\PhpWord\Reader\Word2007\Endnotes', 'xml' => '{toReplace}'), + 'settings' => array('class' => 'PhpOffice\PhpWord\Reader\Word2007\Settings', 'xml' => '{toReplace}'), + ); + /** * Builds a PhpWord instance based on the xml passed * * @param string $documentXml + * @param null|string $stylesXml * @return \PhpOffice\PhpWord\PhpWord */ - protected function getDocumentFromString($documentXml) + protected function getDocumentFromString(array $partXmls = array()) { - $phpWord = new PhpWord(); $file = __DIR__ . '/../_files/temp.docx'; $zip = new \ZipArchive(); $zip->open($file, \ZipArchive::CREATE); - $zip->addFromString('document.xml', '' . $documentXml . ''); + foreach ($this->parts as $partName => $part) { + if (array_key_exists($partName, $partXmls)) { + $zip->addFromString("{$partName}.xml", str_replace('{toReplace}', $partXmls[$partName], $this->parts[$partName]['xml'])); + } + } $zip->close(); - $documentReader = new Document($file, 'document.xml'); - $documentReader->read($phpWord); + + $phpWord = new PhpWord(); + foreach ($this->parts as $partName => $part) { + if (array_key_exists($partName, $partXmls)) { + $className = $this->parts[$partName]['class']; + $reader = new $className($file, "{$partName}.xml"); + $reader->read($phpWord); + } + } unlink($file); return $phpWord; } - - /** - * Returns the element at position $index in the array - * - * @param array $array - * @param number $index - * @return mixed - */ - protected function get(array $array, $index = 0) - { - return $array[$index]; - } } From 250fbd49b1fcaea5412a6860bdc1b38780e8327e Mon Sep 17 00:00:00 2001 From: troosan Date: Tue, 6 Mar 2018 06:35:43 +0100 Subject: [PATCH 046/135] Added support for Vertically Raised or Lowered Text (w:position) (#1294) * Added support for Vertically Raised or Lowered Text (w:position). Note that only docx writing is implemented for now. * Add tests + changelog * add reader + tests + doc --- CHANGELOG.md | 1 + docs/styles.rst | 1 + src/PhpWord/Reader/Word2007/AbstractPart.php | 1 + src/PhpWord/Style/Font.php | 34 +++++++++++++++++++ src/PhpWord/Style/Frame.php | 31 +++++++++++++++++ src/PhpWord/Writer/Word2007/Element/Image.php | 13 +++++++ src/PhpWord/Writer/Word2007/Style/Font.php | 3 ++ tests/PhpWord/Reader/Word2007/StyleTest.php | 24 +++++++++++++ .../Writer/Word2007/Style/FontTest.php | 15 ++++++++ 9 files changed, 123 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f527746f8..1c52179c51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ v0.15.0 (?? ??? 2018) - Add support for fixed Table Layout @aoloe @ekopach @troosan #841 #1276 - Add support for Cell Spacing @dox07 @troosan #1040 - Add parsing of formatting inside lists @atomicalnet @troosan #594 +- Added support for Vertically Raised or Lowered Text (w:position) @anrikun @troosan #640 - Add support for MACROBUTTON field @phryneas @troosan #1021 ### Fixed diff --git a/docs/styles.rst b/docs/styles.rst index 0ec0ec38d5..b84f76f027 100644 --- a/docs/styles.rst +++ b/docs/styles.rst @@ -59,6 +59,7 @@ Available Font style options: See ``\PhpOffice\PhpWord\Style\Font::UNDERLINE_...`` constants for more values - ``lang``. Language, either a language code like *en-US*, *fr-BE*, etc. or an object (or as an array) if you need to set eastAsian or bidirectional languages See ``\PhpOffice\PhpWord\Style\Language`` class for some language codes. +- ``position``. The text position, raised or lowered, in half points .. _paragraph-style: diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index f8a26ddb2e..b4610d283c 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -422,6 +422,7 @@ protected function readFontStyle(XMLReader $xmlReader, \DOMElement $domNode) 'fgColor' => array(self::READ_VALUE, 'w:highlight'), 'rtl' => array(self::READ_TRUE, 'w:rtl'), 'lang' => array(self::READ_VALUE, 'w:lang'), + 'position' => array(self::READ_VALUE, 'w:position'), ); return $this->readStyleDefs($xmlReader, $styleNode, $styleDefs); diff --git a/src/PhpWord/Style/Font.php b/src/PhpWord/Style/Font.php index 03fb692c97..3095b79928 100644 --- a/src/PhpWord/Style/Font.php +++ b/src/PhpWord/Style/Font.php @@ -232,6 +232,7 @@ class Font extends AbstractStyle /** * Right to left languages + * * @var bool */ private $rtl = false; @@ -246,10 +247,19 @@ class Font extends AbstractStyle /** * Languages + * * @var \PhpOffice\PhpWord\Style\Language */ private $lang; + /** + * Vertically Raised or Lowered Text + * + * @var int Signed Half-Point Measurement + * @see http://www.datypic.com/sc/ooxml/e-w_position-1.html + */ + private $position; + /** * Create new font style * @@ -294,6 +304,7 @@ public function getStyleValues() 'scale' => $this->getScale(), 'spacing' => $this->getSpacing(), 'kerning' => $this->getKerning(), + 'position' => $this->getPosition(), ), 'paragraph' => $this->getParagraph(), 'rtl' => $this->isRTL(), @@ -926,4 +937,27 @@ public function getParagraphStyle() { return $this->getParagraph(); } + + /** + * Get position + * + * @return int + */ + public function getPosition() + { + return $this->position; + } + + /** + * Set position + * + * @param int $value + * @return self + */ + public function setPosition($value = null) + { + $this->position = $this->setIntVal($value, null); + + return $this; + } } diff --git a/src/PhpWord/Style/Frame.php b/src/PhpWord/Style/Frame.php index a8e1c69d20..bb684409b9 100644 --- a/src/PhpWord/Style/Frame.php +++ b/src/PhpWord/Style/Frame.php @@ -171,6 +171,14 @@ class Frame extends AbstractStyle */ private $wrap; + /** + * Vertically raised or lowered text + * + * @var int + * @see http://www.datypic.com/sc/ooxml/e-w_position-1.html + */ + private $position; + /** * Create a new instance * @@ -538,4 +546,27 @@ public function setWrap($value) return $this; } + + /** + * Get position + * + * @return int + */ + public function getPosition() + { + return $this->position; + } + + /** + * Set position + * + * @param int $value + * @return self + */ + public function setPosition($value = null) + { + $this->position = $this->setIntVal($value, null); + + return $this; + } } diff --git a/src/PhpWord/Writer/Word2007/Element/Image.php b/src/PhpWord/Writer/Word2007/Element/Image.php index 7e33f75e4f..32a22a132f 100644 --- a/src/PhpWord/Writer/Word2007/Element/Image.php +++ b/src/PhpWord/Writer/Word2007/Element/Image.php @@ -19,6 +19,9 @@ use PhpOffice\Common\XMLWriter; use PhpOffice\PhpWord\Element\Image as ImageElement; +use PhpOffice\PhpWord\Style\Font as FontStyle; +use PhpOffice\PhpWord\Style\Frame as FrameStyle; +use PhpOffice\PhpWord\Writer\Word2007\Style\Font as FontStyleWriter; use PhpOffice\PhpWord\Writer\Word2007\Style\Image as ImageStyleWriter; /** @@ -62,6 +65,16 @@ private function writeImage(XMLWriter $xmlWriter, ImageElement $element) $this->writeCommentRangeStart(); $xmlWriter->startElement('w:r'); + + // Write position + $position = $style->getPosition(); + if ($position && $style->getWrap() == FrameStyle::WRAP_INLINE) { + $fontStyle = new FontStyle('text'); + $fontStyle->setPosition($position); + $fontStyleWriter = new FontStyleWriter($xmlWriter, $fontStyle); + $fontStyleWriter->write(); + } + $xmlWriter->startElement('w:pict'); $xmlWriter->startElement('v:shape'); $xmlWriter->writeAttribute('type', '#_x0000_t75'); diff --git a/src/PhpWord/Writer/Word2007/Style/Font.php b/src/PhpWord/Writer/Word2007/Style/Font.php index a13db155db..5f2a84c0f4 100644 --- a/src/PhpWord/Writer/Word2007/Style/Font.php +++ b/src/PhpWord/Writer/Word2007/Style/Font.php @@ -151,6 +151,9 @@ private function writeStyle() $xmlWriter->writeElementIf($styleName === null && $style->isRTL(), 'w:rtl'); } + // Position + $xmlWriter->writeElementIf($style->getPosition() !== null, 'w:position', 'w:val', $style->getPosition()); + $xmlWriter->endElement(); } diff --git a/tests/PhpWord/Reader/Word2007/StyleTest.php b/tests/PhpWord/Reader/Word2007/StyleTest.php index c0d5d864d1..ad8f125a4c 100644 --- a/tests/PhpWord/Reader/Word2007/StyleTest.php +++ b/tests/PhpWord/Reader/Word2007/StyleTest.php @@ -66,4 +66,28 @@ public function testReadCellSpacing() $tableStyle = $elements[0]->getStyle(); $this->assertEquals(10.5, $tableStyle->getCellSpacing()); } + + /** + * Test reading of position + */ + public function testReadPosition() + { + $documentXml = ' + + + + + This text is lowered + + '; + + $phpWord = $this->getDocumentFromString($documentXml); + + $elements = $this->get($phpWord->getSections(), 0)->getElements(); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $elements[0]); + $this->assertInstanceOf('PhpOffice\PhpWord\Style\Font', $elements[0]->getFontStyle()); + /** @var \PhpOffice\PhpWord\Style\Font $fontStyle */ + $fontStyle = $elements[0]->getFontStyle(); + $this->assertEquals(15, $fontStyle->getPosition()); + } } diff --git a/tests/PhpWord/Writer/Word2007/Style/FontTest.php b/tests/PhpWord/Writer/Word2007/Style/FontTest.php index d36a303718..f66cf24ff4 100644 --- a/tests/PhpWord/Writer/Word2007/Style/FontTest.php +++ b/tests/PhpWord/Writer/Word2007/Style/FontTest.php @@ -65,4 +65,19 @@ public function testFontWithLang() $path = '/w:document/w:body/w:p/w:r/w:rPr/w:lang'; $this->assertTrue($doc->elementExists($path, $file)); } + + /** + * Test writing position + */ + public function testPosition() + { + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + $section->addText('This text is lowered', array('position' => -20)); + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $path = '/w:document/w:body/w:p/w:r/w:rPr/w:position'; + $this->assertTrue($doc->elementExists($path)); + $this->assertEquals(-20, $doc->getElementAttribute($path, 'w:val')); + } } From 6a6497956da91d3a9d4ab44d9df2c2ed31bfb8dd Mon Sep 17 00:00:00 2001 From: Frank Liepert Date: Tue, 6 Mar 2018 22:19:40 +0100 Subject: [PATCH 047/135] Allow to set "autoHyphenation" setting (#1282) * Allow to set "autoHyphenation" for document * Allow to set "consecutiveHyphenLimit" for document * Allow to set "hyphenationZone" for document * Allow to set "doNotHyphenateCaps" for document * Allow to set "suppressAutoHyphens" for paragraph * randomize the tempDir more * Word2007 parsing title formatting (#1297) * Improve Title parsing - Title should be able to contain TextRun - Style 'Title' should be treated the same with as Heading - Add tests for Heading/Title reader * update the documentation and the changelog * PHP 7.2 build should not fail anymore * fix parsing of footnotes and endnotes * add method to remove an element from a section * add method to allow sorting of sections --- CHANGELOG.md | 3 +- docs/general.rst | 46 +++++++++- docs/styles.rst | 1 + src/PhpWord/Element/Field.php | 42 --------- src/PhpWord/Metadata/Settings.php | 90 +++++++++++++++++++ src/PhpWord/PhpWord.php | 11 +++ src/PhpWord/Reader/Word2007/AbstractPart.php | 31 +++---- src/PhpWord/Reader/Word2007/Settings.php | 41 ++++++++- src/PhpWord/Shared/Html.php | 2 +- src/PhpWord/Style/Paragraph.php | 62 +++++++++---- src/PhpWord/Writer/ODText/Part/Content.php | 10 +-- src/PhpWord/Writer/Word2007/Part/Settings.php | 48 ++++++++-- .../Writer/Word2007/Style/Paragraph.php | 3 + tests/PhpWord/Element/SectionTest.php | 4 +- tests/PhpWord/Metadata/SettingsTest.php | 54 +++++++++++ tests/PhpWord/PhpWordTest.php | 54 +++++++++++ tests/PhpWord/Reader/Word2007/StyleTest.php | 4 +- tests/PhpWord/Style/ParagraphTest.php | 35 ++++---- .../Writer/Word2007/Part/SettingsTest.php | 64 +++++++++++++ .../Writer/Word2007/Style/ParagraphTest.php | 15 ++++ 20 files changed, 506 insertions(+), 114 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c52179c51..cdc4d67cd4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ v0.15.0 (?? ??? 2018) - Add parsing of formatting inside lists @atomicalnet @troosan #594 - Added support for Vertically Raised or Lowered Text (w:position) @anrikun @troosan #640 - Add support for MACROBUTTON field @phryneas @troosan #1021 +- Add support for Hyphenation @Trainmaster #1282 (Document: `autoHyphenation`, `consecutiveHyphenLimit`, `hyphenationZone`, `doNotHyphenateCaps`, Paragraph: `suppressAutoHyphens`) ### Fixed - Fix reading of docx default style - @troosan #1238 @@ -477,4 +478,4 @@ This is the first release after a long development hiatus in [CodePlex](https:// - Basic CI with Travis - @Progi1984 - Added PHPWord_Exception and exception when could not copy the template - @Progi1984 - IMPROVED: Moved examples out of Classes directory - @Progi1984 -- IMPROVED: Advanced string replace in setValue for Template - @Esmeraldo [#49](http://phpword.codeplex.com/workitem/49) \ No newline at end of file +- IMPROVED: Advanced string replace in setValue for Template - @Esmeraldo [#49](http://phpword.codeplex.com/workitem/49) diff --git a/docs/general.rst b/docs/general.rst index 99d8b3bac0..f40a08c367 100644 --- a/docs/general.rst +++ b/docs/general.rst @@ -217,10 +217,10 @@ The default language of the document can be change with the following. $phpWord->getSettings()->setThemeFontLang(new Language(Language::FR_BE)); -``Languge`` has 3 parameters, one for Latin languages, one for East Asian languages and one for Complex (Bi-Directional) languages. +``Language`` has 3 parameters, one for Latin languages, one for East Asian languages and one for Complex (Bi-Directional) languages. A couple of language codes are provided in the ``PhpOffice\PhpWord\ComplexType\Language`` class but any valid code/ID can be used. -In case you are generating an RTF document the Language need to be set differently. +In case you are generating an RTF document the language need to be set differently. .. code-block:: php @@ -290,3 +290,45 @@ To force an update of the fields present in the document, set updateFields to tr .. code-block:: php $phpWord->getSettings()->setUpdateFields(true); + +Hyphenation +----------- +Hyphenation describes the process of breaking words with hyphens. There are several options to control hyphenation. + +Auto hyphenation +~~~~~~~~~~~~~~~~ + +To automatically hyphenate text set ``autoHyphenation`` to ``true``. + +.. code-block:: php + + $phpWord->getSettings()->setAutoHyphenation(true); + +Consecutive Hyphen Limit +~~~~~~~~~~~~~~~~~~~~~~~~ + +The maximum number of consecutive lines of text ending with a hyphen can be controlled by the ``consecutiveHyphenLimit`` option. +There is no limit if the option is not set or the provided value is ``0``. + +.. code-block:: php + + $phpWord->getSettings()->setConsecutiveHyphenLimit(2); + +Hyphenation Zone +~~~~~~~~~~~~~~~~ + +The hyphenation zone (in *twip*) is the allowed amount of whitespace before hyphenation is applied. +The smaller the hyphenation zone the more words are hyphenated. Or in other words, the wider the hyphenation zone the less words are hyphenated. + +.. code-block:: php + + $phpWord->getSettings()->setHyphenationZone(\PhpOffice\PhpWord\Shared\Converter::cmToTwip(1)); + +Hyphenate Caps +~~~~~~~~~~~~~~ + +To control whether or not words in all capital letters shall be hyphenated use the `doNotHyphenateCaps` option. + +.. code-block:: php + + $phpWord->getSettings()->setDoNotHyphenateCaps(true); diff --git a/docs/styles.rst b/docs/styles.rst index b84f76f027..b4ed328d45 100644 --- a/docs/styles.rst +++ b/docs/styles.rst @@ -82,6 +82,7 @@ Available Paragraph style options: - ``spaceAfter``. Space after paragraph in *twip*. - ``spacing``. Space between lines. - ``spacingLineRule``. Line Spacing Rule. *auto*, *exact*, *atLeast* +- ``suppressAutoHyphens``. Hyphenation for paragraph, *true* or *false*. - ``tabs``. Set of custom tab stops. - ``widowControl``. Allow first/last line to display on a separate page, *true* or *false*. - ``contextualSpacing``. Ignore Spacing Above and Below When Using Identical Styles, *true* or *false*. diff --git a/src/PhpWord/Element/Field.php b/src/PhpWord/Element/Field.php index 5aeffbc168..de50496520 100644 --- a/src/PhpWord/Element/Field.php +++ b/src/PhpWord/Element/Field.php @@ -17,8 +17,6 @@ namespace PhpOffice\PhpWord\Element; -use PhpOffice\PhpWord\Style\Font; - /** * Field element * @@ -215,46 +213,6 @@ public function getOptions() return $this->options; } - /** - * Set Text style - * - * @param \PhpOffice\PhpWord\Style\Font $style - * @return \PhpOffice\PhpWord\Style\Font - */ - public function setFontStyle($style = null) - { - if (!$style instanceof Font) { - throw new \InvalidArgumentException('font style must be of type Font'); - } - - if ($style->isNoProof()) { - $this->fontStyle = $style; - } else { - // make a copy of the font so the original is not altered - $this->fontStyle = clone $style; - $this->fontStyle->setNoProof(true); - } - - return $this->fontStyle; - } - - /** - * Get Text style - * - * @return \PhpOffice\PhpWord\Style\Font - */ - public function getFontStyle() - { - if ($this->fontStyle == null) { - $font = new Font(); - $font->setNoProof(true); - - return $font; - } - - return $this->fontStyle; - } - /** * Set Field text * diff --git a/src/PhpWord/Metadata/Settings.php b/src/PhpWord/Metadata/Settings.php index 728cc823fd..8ab5860948 100644 --- a/src/PhpWord/Metadata/Settings.php +++ b/src/PhpWord/Metadata/Settings.php @@ -130,6 +130,32 @@ class Settings */ private $decimalSymbol = '.'; + /** + * Automatically hyphenate document contents when displayed + * + * @var bool|null + */ + private $autoHyphenation; + + /** + * Maximum number of consecutively hyphenated lines + * + * @var int|null + */ + private $consecutiveHyphenLimit; + + /** + * The allowed amount of whitespace before hyphenation is applied + * @var float|null + */ + private $hyphenationZone; + + /** + * Do not hyphenate words in all capital letters + * @var bool|null + */ + private $doNotHyphenateCaps; + /** * @return Protection */ @@ -387,4 +413,68 @@ public function setDecimalSymbol($decimalSymbol) { $this->decimalSymbol = $decimalSymbol; } + + /** + * @return bool|null + */ + public function hasAutoHyphenation() + { + return $this->autoHyphenation; + } + + /** + * @param bool $autoHyphenation + */ + public function setAutoHyphenation($autoHyphenation) + { + $this->autoHyphenation = (bool) $autoHyphenation; + } + + /** + * @return int|null + */ + public function getConsecutiveHyphenLimit() + { + return $this->consecutiveHyphenLimit; + } + + /** + * @param int $consecutiveHyphenLimit + */ + public function setConsecutiveHyphenLimit($consecutiveHyphenLimit) + { + $this->consecutiveHyphenLimit = (int) $consecutiveHyphenLimit; + } + + /** + * @return float|null + */ + public function getHyphenationZone() + { + return $this->hyphenationZone; + } + + /** + * @param float $hyphenationZone Measurement unit is twip + */ + public function setHyphenationZone($hyphenationZone) + { + $this->hyphenationZone = $hyphenationZone; + } + + /** + * @return null|bool + */ + public function hasDoNotHyphenateCaps() + { + return $this->doNotHyphenateCaps; + } + + /** + * @param bool $doNotHyphenateCaps + */ + public function setDoNotHyphenateCaps($doNotHyphenateCaps) + { + $this->doNotHyphenateCaps = (bool) $doNotHyphenateCaps; + } } diff --git a/src/PhpWord/PhpWord.php b/src/PhpWord/PhpWord.php index 54ef65ac97..ff23f6ef25 100644 --- a/src/PhpWord/PhpWord.php +++ b/src/PhpWord/PhpWord.php @@ -242,6 +242,17 @@ public function addSection($style = null) return $section; } + /** + * Sorts the sections using the callable passed + * + * @see http://php.net/manual/en/function.usort.php for usage + * @param callable $sorter + */ + public function sortSections($sorter) + { + usort($this->sections, $sorter); + } + /** * Get default font name * diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index b4610d283c..2cbfba37cc 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -364,20 +364,21 @@ protected function readParagraphStyle(XMLReader $xmlReader, \DOMElement $domNode $styleNode = $xmlReader->getElement('w:pPr', $domNode); $styleDefs = array( - 'styleName' => array(self::READ_VALUE, array('w:pStyle', 'w:name')), - 'alignment' => array(self::READ_VALUE, 'w:jc'), - 'basedOn' => array(self::READ_VALUE, 'w:basedOn'), - 'next' => array(self::READ_VALUE, 'w:next'), - 'indent' => array(self::READ_VALUE, 'w:ind', 'w:left'), - 'hanging' => array(self::READ_VALUE, 'w:ind', 'w:hanging'), - 'spaceAfter' => array(self::READ_VALUE, 'w:spacing', 'w:after'), - 'spaceBefore' => array(self::READ_VALUE, 'w:spacing', 'w:before'), - 'widowControl' => array(self::READ_FALSE, 'w:widowControl'), - 'keepNext' => array(self::READ_TRUE, 'w:keepNext'), - 'keepLines' => array(self::READ_TRUE, 'w:keepLines'), - 'pageBreakBefore' => array(self::READ_TRUE, 'w:pageBreakBefore'), - 'contextualSpacing' => array(self::READ_TRUE, 'w:contextualSpacing'), - 'bidi' => array(self::READ_TRUE, 'w:bidi'), + 'styleName' => array(self::READ_VALUE, array('w:pStyle', 'w:name')), + 'alignment' => array(self::READ_VALUE, 'w:jc'), + 'basedOn' => array(self::READ_VALUE, 'w:basedOn'), + 'next' => array(self::READ_VALUE, 'w:next'), + 'indent' => array(self::READ_VALUE, 'w:ind', 'w:left'), + 'hanging' => array(self::READ_VALUE, 'w:ind', 'w:hanging'), + 'spaceAfter' => array(self::READ_VALUE, 'w:spacing', 'w:after'), + 'spaceBefore' => array(self::READ_VALUE, 'w:spacing', 'w:before'), + 'widowControl' => array(self::READ_FALSE, 'w:widowControl'), + 'keepNext' => array(self::READ_TRUE, 'w:keepNext'), + 'keepLines' => array(self::READ_TRUE, 'w:keepLines'), + 'pageBreakBefore' => array(self::READ_TRUE, 'w:pageBreakBefore'), + 'contextualSpacing' => array(self::READ_TRUE, 'w:contextualSpacing'), + 'bidi' => array(self::READ_TRUE, 'w:bidi'), + 'suppressAutoHyphens' => array(self::READ_TRUE, 'w:suppressAutoHyphens'), ); return $this->readStyleDefs($xmlReader, $styleNode, $styleDefs); @@ -578,7 +579,7 @@ protected function readStyleDefs(XMLReader $xmlReader, \DOMElement $parentNode = * * @param string $method * @ignoreScrutinizerPatch - * @param mixed $attributeValue + * @param string|null $attributeValue * @param mixed $expected * @return mixed */ diff --git a/src/PhpWord/Reader/Word2007/Settings.php b/src/PhpWord/Reader/Word2007/Settings.php index 581a546d09..ee057fe674 100644 --- a/src/PhpWord/Reader/Word2007/Settings.php +++ b/src/PhpWord/Reader/Word2007/Settings.php @@ -29,7 +29,18 @@ */ class Settings extends AbstractPart { - private static $booleanProperties = array('hideSpellingErrors', 'hideGrammaticalErrors', 'trackRevisions', 'doNotTrackMoves', 'doNotTrackFormatting', 'evenAndOddHeaders'); + private static $booleanProperties = array( + 'mirrorMargins', + 'hideSpellingErrors', + 'hideGrammaticalErrors', + 'trackRevisions', + 'doNotTrackMoves', + 'doNotTrackFormatting', + 'evenAndOddHeaders', + 'updateFields', + 'autoHyphenation', + 'doNotHyphenateCaps', + ); /** * Read settings.xml. @@ -157,4 +168,32 @@ protected function setRevisionView(XMLReader $xmlReader, PhpWord $phpWord, \DOME $revisionView->setInkAnnotations(filter_var($xmlReader->getAttribute('w:inkAnnotations', $node), FILTER_VALIDATE_BOOLEAN)); $phpWord->getSettings()->setRevisionView($revisionView); } + + /** + * @param XMLReader $xmlReader + * @param PhpWord $phpWord + * @param \DOMElement $node + */ + protected function setConsecutiveHyphenLimit(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node) + { + $value = $xmlReader->getAttribute('w:val', $node); + + if ($value !== null) { + $phpWord->getSettings()->setConsecutiveHyphenLimit($value); + } + } + + /** + * @param XMLReader $xmlReader + * @param PhpWord $phpWord + * @param \DOMElement $node + */ + protected function setHyphenationZone(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node) + { + $value = $xmlReader->getAttribute('w:val', $node); + + if ($value !== null) { + $phpWord->getSettings()->setHyphenationZone($value); + } + } } diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 7363580753..2c7cf1b5da 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -252,7 +252,7 @@ private static function parseText($node, $element, &$styles) $styles['font'] = self::recursiveParseStylesInHierarchy($node, $styles['font']); //alignment applies on paragraph, not on font. Let's copy it there - if (isset($styles['font']['alignment'])) { + if (isset($styles['font']['alignment']) && is_array($styles['paragraph'])) { $styles['paragraph']['alignment'] = $styles['font']['alignment']; } diff --git a/src/PhpWord/Style/Paragraph.php b/src/PhpWord/Style/Paragraph.php index 7e40d9e403..53a9b958fc 100644 --- a/src/PhpWord/Style/Paragraph.php +++ b/src/PhpWord/Style/Paragraph.php @@ -180,6 +180,13 @@ class Paragraph extends Border */ private $textAlignment; + /** + * Suppress hyphenation for paragraph + * + * @var bool + */ + private $suppressAutoHyphens = false; + /** * Set Style value * @@ -212,27 +219,28 @@ public function setStyleValue($key, $value) public function getStyleValues() { $styles = array( - 'name' => $this->getStyleName(), - 'basedOn' => $this->getBasedOn(), - 'next' => $this->getNext(), - 'alignment' => $this->getAlignment(), - 'indentation' => $this->getIndentation(), - 'spacing' => $this->getSpace(), - 'pagination' => array( - 'widowControl' => $this->hasWidowControl(), - 'keepNext' => $this->isKeepNext(), - 'keepLines' => $this->isKeepLines(), - 'pageBreak' => $this->hasPageBreakBefore(), + 'name' => $this->getStyleName(), + 'basedOn' => $this->getBasedOn(), + 'next' => $this->getNext(), + 'alignment' => $this->getAlignment(), + 'indentation' => $this->getIndentation(), + 'spacing' => $this->getSpace(), + 'pagination' => array( + 'widowControl' => $this->hasWidowControl(), + 'keepNext' => $this->isKeepNext(), + 'keepLines' => $this->isKeepLines(), + 'pageBreak' => $this->hasPageBreakBefore(), ), - 'numbering' => array( - 'style' => $this->getNumStyle(), - 'level' => $this->getNumLevel(), + 'numbering' => array( + 'style' => $this->getNumStyle(), + 'level' => $this->getNumLevel(), ), - 'tabs' => $this->getTabs(), - 'shading' => $this->getShading(), - 'contextualSpacing' => $this->hasContextualSpacing(), - 'bidi' => $this->isBidi(), - 'textAlignment' => $this->getTextAlignment(), + 'tabs' => $this->getTabs(), + 'shading' => $this->getShading(), + 'contextualSpacing' => $this->hasContextualSpacing(), + 'bidi' => $this->isBidi(), + 'textAlignment' => $this->getTextAlignment(), + 'suppressAutoHyphens' => $this->hasSuppressAutoHyphens(), ); return $styles; @@ -848,4 +856,20 @@ public function setTextAlignment($textAlignment) return $this; } + + /** + * @return bool + */ + public function hasSuppressAutoHyphens() + { + return $this->suppressAutoHyphens; + } + + /** + * @param bool $suppressAutoHyphens + */ + public function setSuppressAutoHyphens($suppressAutoHyphens) + { + $this->suppressAutoHyphens = (bool) $suppressAutoHyphens; + } } diff --git a/src/PhpWord/Writer/ODText/Part/Content.php b/src/PhpWord/Writer/ODText/Part/Content.php index 19d3e54ab0..f91ad5441e 100644 --- a/src/PhpWord/Writer/ODText/Part/Content.php +++ b/src/PhpWord/Writer/ODText/Part/Content.php @@ -222,8 +222,8 @@ private function getAutoStyles(PhpWord $phpWord) * Table style can be null or string of the style name * * @param \PhpOffice\PhpWord\Element\AbstractContainer $container - * @param int &$paragraphStyleCount - * @param int &$fontStyleCount + * @param int $paragraphStyleCount + * @param int $fontStyleCount * @todo Simplify the logic */ private function getContainerStyle($container, &$paragraphStyleCount, &$fontStyleCount) @@ -254,9 +254,9 @@ private function getContainerStyle($container, &$paragraphStyleCount, &$fontStyl /** * Get style of individual element * - * @param \PhpOffice\PhpWord\Element\Text &$element - * @param int &$paragraphStyleCount - * @param int &$fontStyleCount + * @param \PhpOffice\PhpWord\Element\Text $element + * @param int $paragraphStyleCount + * @param int $fontStyleCount */ private function getElementStyle(&$element, &$paragraphStyleCount, &$fontStyleCount) { diff --git a/src/PhpWord/Writer/Word2007/Part/Settings.php b/src/PhpWord/Writer/Word2007/Part/Settings.php index e56e2612bd..463ce0828d 100644 --- a/src/PhpWord/Writer/Word2007/Part/Settings.php +++ b/src/PhpWord/Writer/Word2007/Part/Settings.php @@ -149,12 +149,16 @@ private function getSettings() $this->setOnOffValue('w:doNotTrackFormatting', $documentSettings->hasDoNotTrackFormatting()); $this->setOnOffValue('w:evenAndOddHeaders', $documentSettings->hasEvenAndOddHeaders()); $this->setOnOffValue('w:updateFields', $documentSettings->hasUpdateFields()); + $this->setOnOffValue('w:autoHyphenation', $documentSettings->hasAutoHyphenation()); + $this->setOnOffValue('w:doNotHyphenateCaps', $documentSettings->hasDoNotHyphenateCaps()); $this->setThemeFontLang($documentSettings->getThemeFontLang()); $this->setRevisionView($documentSettings->getRevisionView()); $this->setDocumentProtection($documentSettings->getDocumentProtection()); $this->setProofState($documentSettings->getProofState()); $this->setZoom($documentSettings->getZoom()); + $this->setConsecutiveHyphenLimit($documentSettings->getConsecutiveHyphenLimit()); + $this->setHyphenationZone($documentSettings->getHyphenationZone()); $this->setCompatibility(); } @@ -162,16 +166,18 @@ private function getSettings() * Adds a boolean attribute to the settings array * * @param string $settingName - * @param bool $booleanValue + * @param bool|null $booleanValue */ private function setOnOffValue($settingName, $booleanValue) { - if ($booleanValue !== null && is_bool($booleanValue)) { - if ($booleanValue) { - $this->settings[$settingName] = array('@attributes' => array()); - } else { - $this->settings[$settingName] = array('@attributes' => array('w:val' => 'false')); - } + if (!is_bool($booleanValue)) { + return; + } + + if ($booleanValue) { + $this->settings[$settingName] = array('@attributes' => array()); + } else { + $this->settings[$settingName] = array('@attributes' => array('w:val' => 'false')); } } @@ -278,6 +284,34 @@ private function setZoom($zoom = null) } } + /** + * @param int|null $consecutiveHyphenLimit + */ + private function setConsecutiveHyphenLimit($consecutiveHyphenLimit) + { + if ($consecutiveHyphenLimit === null) { + return; + } + + $this->settings['w:consecutiveHyphenLimit'] = array( + '@attributes' => array('w:val' => $consecutiveHyphenLimit), + ); + } + + /** + * @param float|null $hyphenationZone + */ + private function setHyphenationZone($hyphenationZone) + { + if ($hyphenationZone === null) { + return; + } + + $this->settings['w:hyphenationZone'] = array( + '@attributes' => array('w:val' => $hyphenationZone), + ); + } + /** * Get compatibility setting. */ diff --git a/src/PhpWord/Writer/Word2007/Style/Paragraph.php b/src/PhpWord/Writer/Word2007/Style/Paragraph.php index 8915fb4c70..eeccc5c87e 100644 --- a/src/PhpWord/Writer/Word2007/Style/Paragraph.php +++ b/src/PhpWord/Writer/Word2007/Style/Paragraph.php @@ -112,6 +112,9 @@ private function writeStyle() //Paragraph textAlignment $xmlWriter->writeElementIf($styles['textAlignment'] !== null, 'w:textAlignment', 'w:val', $styles['textAlignment']); + // Hyphenation + $xmlWriter->writeElementIf($styles['suppressAutoHyphens'] === true, 'w:suppressAutoHyphens'); + // Child style: alignment, indentation, spacing, and shading $this->writeChildStyle($xmlWriter, 'Indentation', $styles['indentation']); $this->writeChildStyle($xmlWriter, 'Spacing', $styles['spacing']); diff --git a/tests/PhpWord/Element/SectionTest.php b/tests/PhpWord/Element/SectionTest.php index 867f680aeb..37096e2d9e 100644 --- a/tests/PhpWord/Element/SectionTest.php +++ b/tests/PhpWord/Element/SectionTest.php @@ -184,11 +184,11 @@ public function testRemoveElementByIndex() public function testRemoveElementByElement() { $section = new Section(1); - $fistText = $section->addText('firstText'); + $firstText = $section->addText('firstText'); $secondText = $section->addText('secondText'); $this->assertEquals(2, $section->countElements()); - $section->removeElement($fistText); + $section->removeElement($firstText); $this->assertEquals(1, $section->countElements()); $this->assertEquals($secondText->getElementId(), $section->getElement(1)->getElementId()); diff --git a/tests/PhpWord/Metadata/SettingsTest.php b/tests/PhpWord/Metadata/SettingsTest.php index 508635616f..07dc896291 100644 --- a/tests/PhpWord/Metadata/SettingsTest.php +++ b/tests/PhpWord/Metadata/SettingsTest.php @@ -172,4 +172,58 @@ public function testUpdateFields() $oSettings->setUpdateFields(true); $this->assertTrue($oSettings->hasUpdateFields()); } + + public function testAutoHyphenation() + { + $oSettings = new Settings(); + $oSettings->setAutoHyphenation(true); + $this->assertTrue($oSettings->hasAutoHyphenation()); + } + + public function testDefaultAutoHyphenation() + { + $oSettings = new Settings(); + $this->assertNull($oSettings->hasAutoHyphenation()); + } + + public function testConsecutiveHyphenLimit() + { + $consecutiveHypenLimit = 2; + $oSettings = new Settings(); + $oSettings->setConsecutiveHyphenLimit($consecutiveHypenLimit); + $this->assertSame($consecutiveHypenLimit, $oSettings->getConsecutiveHyphenLimit()); + } + + public function testDefaultConsecutiveHyphenLimit() + { + $oSettings = new Settings(); + $this->assertNull($oSettings->getConsecutiveHyphenLimit()); + } + + public function testHyphenationZone() + { + $hyphenationZoneInTwip = 100; + $oSettings = new Settings(); + $oSettings->setHyphenationZone($hyphenationZoneInTwip); + $this->assertSame($hyphenationZoneInTwip, $oSettings->getHyphenationZone()); + } + + public function testDefaultHyphenationZone() + { + $oSettings = new Settings(); + $this->assertNull($oSettings->getHyphenationZone()); + } + + public function testDoNotHyphenateCaps() + { + $oSettings = new Settings(); + $oSettings->setDoNotHyphenateCaps(true); + $this->assertTrue($oSettings->hasDoNotHyphenateCaps()); + } + + public function testDefaultDoNotHyphenateCaps() + { + $oSettings = new Settings(); + $this->assertNull($oSettings->hasDoNotHyphenateCaps()); + } } diff --git a/tests/PhpWord/PhpWordTest.php b/tests/PhpWord/PhpWordTest.php index f8a224591c..3b1b5a3611 100644 --- a/tests/PhpWord/PhpWordTest.php +++ b/tests/PhpWord/PhpWordTest.php @@ -171,4 +171,58 @@ public function testCallUndefinedMethod() $phpWord = new PhpWord(); $phpWord->undefinedMethod(); } + + /** + * @covers \PhpOffice\PhpWord\PhpWord::getSection + */ + public function testGetNotExistingSection() + { + $phpWord = new PhpWord(); + $section = $phpWord->getSection(0); + + $this->assertNull($section); + } + + /** + * @covers \PhpOffice\PhpWord\PhpWord::getSection + */ + public function testGetSection() + { + $phpWord = new PhpWord(); + $phpWord->addSection(); + $section = $phpWord->getSection(0); + + $this->assertNotNull($section); + } + + /** + * @covers \PhpOffice\PhpWord\PhpWord::sortSections + */ + public function testSortSections() + { + $phpWord = new PhpWord(); + $section1 = $phpWord->addSection(); + $section1->addText('test1'); + $section2 = $phpWord->addSection(); + $section2->addText('test2'); + $section2->addText('test3'); + + $this->assertEquals(1, $phpWord->getSection(0)->countElements()); + $this->assertEquals(2, $phpWord->getSection(1)->countElements()); + + $phpWord->sortSections(function ($a, $b) { + $numElementsInA = $a->countElements(); + $numElementsInB = $b->countElements(); + if ($numElementsInA === $numElementsInB) { + return 0; + } elseif ($numElementsInA > $numElementsInB) { + return -1; + } + + return 1; + }); + + $this->assertEquals(2, $phpWord->getSection(0)->countElements()); + $this->assertEquals(1, $phpWord->getSection(1)->countElements()); + } } diff --git a/tests/PhpWord/Reader/Word2007/StyleTest.php b/tests/PhpWord/Reader/Word2007/StyleTest.php index ad8f125a4c..93e4a1f048 100644 --- a/tests/PhpWord/Reader/Word2007/StyleTest.php +++ b/tests/PhpWord/Reader/Word2007/StyleTest.php @@ -81,9 +81,9 @@ public function testReadPosition() '; - $phpWord = $this->getDocumentFromString($documentXml); + $phpWord = $this->getDocumentFromString(array('document' => $documentXml)); - $elements = $this->get($phpWord->getSections(), 0)->getElements(); + $elements = $phpWord->getSection(0)->getElements(); $this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $elements[0]); $this->assertInstanceOf('PhpOffice\PhpWord\Style\Font', $elements[0]->getFontStyle()); /** @var \PhpOffice\PhpWord\Style\Font $fontStyle */ diff --git a/tests/PhpWord/Style/ParagraphTest.php b/tests/PhpWord/Style/ParagraphTest.php index e961f36a76..adf0ed4d30 100644 --- a/tests/PhpWord/Style/ParagraphTest.php +++ b/tests/PhpWord/Style/ParagraphTest.php @@ -67,23 +67,24 @@ public function testSetStyleValueNormal() $object = new Paragraph(); $attributes = array( - 'spaceAfter' => 240, - 'spaceBefore' => 240, - 'indent' => 1, - 'hanging' => 1, - 'spacing' => 120, - 'spacingLineRule' => LineSpacingRule::AT_LEAST, - 'basedOn' => 'Normal', - 'next' => 'Normal', - 'numStyle' => 'numStyle', - 'numLevel' => 1, - 'widowControl' => false, - 'keepNext' => true, - 'keepLines' => true, - 'pageBreakBefore' => true, - 'contextualSpacing' => true, - 'textAlignment' => 'auto', - 'bidi' => true, + 'spaceAfter' => 240, + 'spaceBefore' => 240, + 'indent' => 1, + 'hanging' => 1, + 'spacing' => 120, + 'spacingLineRule' => LineSpacingRule::AT_LEAST, + 'basedOn' => 'Normal', + 'next' => 'Normal', + 'numStyle' => 'numStyle', + 'numLevel' => 1, + 'widowControl' => false, + 'keepNext' => true, + 'keepLines' => true, + 'pageBreakBefore' => true, + 'contextualSpacing' => true, + 'textAlignment' => 'auto', + 'bidi' => true, + 'suppressAutoHyphens' => true, ); foreach ($attributes as $key => $value) { $get = $this->findGetter($key, $value, $object); diff --git a/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php b/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php index 50b444b80a..a45253a260 100644 --- a/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php +++ b/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php @@ -330,4 +330,68 @@ public function testDoNotTrackFormatting() $element = $doc->getElement($path, $file); $this->assertNotEquals('false', $element->getAttribute('w:val')); } + + public function testAutoHyphenation() + { + $phpWord = new PhpWord(); + $phpWord->getSettings()->setAutoHyphenation(true); + + $doc = TestHelperDOCX::getDocument($phpWord); + + $file = 'word/settings.xml'; + + $path = '/w:settings/w:autoHyphenation'; + $this->assertTrue($doc->elementExists($path, $file)); + + $element = $doc->getElement($path, $file); + $this->assertNotEquals('false', $element->getAttribute('w:val')); + } + + public function testConsecutiveHyphenLimit() + { + $phpWord = new PhpWord(); + $phpWord->getSettings()->setConsecutiveHyphenLimit(2); + + $doc = TestHelperDOCX::getDocument($phpWord); + + $file = 'word/settings.xml'; + + $path = '/w:settings/w:consecutiveHyphenLimit'; + $this->assertTrue($doc->elementExists($path, $file)); + + $element = $doc->getElement($path, $file); + $this->assertSame('2', $element->getAttribute('w:val')); + } + + public function testHyphenationZone() + { + $phpWord = new PhpWord(); + $phpWord->getSettings()->setHyphenationZone(100); + + $doc = TestHelperDOCX::getDocument($phpWord); + + $file = 'word/settings.xml'; + + $path = '/w:settings/w:hyphenationZone'; + $this->assertTrue($doc->elementExists($path, $file)); + + $element = $doc->getElement($path, $file); + $this->assertSame('100', $element->getAttribute('w:val')); + } + + public function testDoNotHyphenateCaps() + { + $phpWord = new PhpWord(); + $phpWord->getSettings()->setDoNotHyphenateCaps(true); + + $doc = TestHelperDOCX::getDocument($phpWord); + + $file = 'word/settings.xml'; + + $path = '/w:settings/w:doNotHyphenateCaps'; + $this->assertTrue($doc->elementExists($path, $file)); + + $element = $doc->getElement($path, $file); + $this->assertNotEquals('false', $element->getAttribute('w:val')); + } } diff --git a/tests/PhpWord/Writer/Word2007/Style/ParagraphTest.php b/tests/PhpWord/Writer/Word2007/Style/ParagraphTest.php index 9bc2756b32..1e5e1d13c7 100644 --- a/tests/PhpWord/Writer/Word2007/Style/ParagraphTest.php +++ b/tests/PhpWord/Writer/Word2007/Style/ParagraphTest.php @@ -17,6 +17,7 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Style; +use PhpOffice\PhpWord\Style\Paragraph as ParagraphStyle; use PhpOffice\PhpWord\TestHelperDOCX; /** @@ -49,4 +50,18 @@ public function testParagraphNumbering() $path = '/w:document/w:body/w:p/w:pPr/w:numPr/w:ilvl'; $this->assertTrue($doc->elementExists($path)); } + + public function testSuppressAutoHyphens() + { + $paragraphStyle = new ParagraphStyle(); + $paragraphStyle->setSuppressAutoHyphens(true); + + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + $section->addText('test', null, $paragraphStyle); + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $path = '/w:document/w:body/w:p/w:pPr/w:suppressAutoHyphens'; + $this->assertTrue($doc->elementExists($path)); + } } From f41c542ba07e02718718a2958b9cfcb427dfb8a0 Mon Sep 17 00:00:00 2001 From: Frank Liepert Date: Thu, 15 Feb 2018 20:08:48 +0100 Subject: [PATCH 048/135] Enforce valid value for on/off type --- src/PhpWord/Writer/Word2007/Part/Settings.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/PhpWord/Writer/Word2007/Part/Settings.php b/src/PhpWord/Writer/Word2007/Part/Settings.php index 463ce0828d..118c0da069 100644 --- a/src/PhpWord/Writer/Word2007/Part/Settings.php +++ b/src/PhpWord/Writer/Word2007/Part/Settings.php @@ -174,11 +174,8 @@ private function setOnOffValue($settingName, $booleanValue) return; } - if ($booleanValue) { - $this->settings[$settingName] = array('@attributes' => array()); - } else { - $this->settings[$settingName] = array('@attributes' => array('w:val' => 'false')); - } + $value = $booleanValue ? 'true' : 'false'; + $this->settings[$settingName] = array('@attributes' => array('w:val' => $value)); } /** From edc3aa3cce59172b138e08475e1732624a2812cd Mon Sep 17 00:00:00 2001 From: Frank Liepert Date: Thu, 15 Feb 2018 20:08:59 +0100 Subject: [PATCH 049/135] Improve assertions --- .../Writer/Word2007/Part/SettingsTest.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php b/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php index a45253a260..41583e375b 100644 --- a/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php +++ b/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php @@ -174,7 +174,7 @@ public function testSpelling() $this->assertTrue($doc->elementExists($path, $file)); $element = $doc->getElement($path, $file); - $this->assertNotEquals('false', $element->getAttribute('w:val')); + $this->assertSame('true', $element->getAttribute('w:val')); } /** @@ -193,7 +193,7 @@ public function testEvenAndOddHeaders() $this->assertTrue($doc->elementExists($path, $file)); $element = $doc->getElement($path, $file); - $this->assertNotEquals('false', $element->getAttribute('w:val')); + $this->assertSame('true', $element->getAttribute('w:val')); } /** @@ -247,7 +247,7 @@ public function testMirrorMargins() $this->assertTrue($doc->elementExists($path, $file)); $element = $doc->getElement($path, $file); - $this->assertNotEquals('false', $element->getAttribute('w:val')); + $this->assertSame('true', $element->getAttribute('w:val')); } /** @@ -290,7 +290,7 @@ public function testTrackRevisions() $this->assertTrue($doc->elementExists($path, $file)); $element = $doc->getElement($path, $file); - $this->assertNotEquals('false', $element->getAttribute('w:val')); + $this->assertSame('true', $element->getAttribute('w:val')); } /** @@ -309,7 +309,7 @@ public function testDoNotTrackMoves() $this->assertTrue($doc->elementExists($path, $file)); $element = $doc->getElement($path, $file); - $this->assertNotEquals('false', $element->getAttribute('w:val')); + $this->assertSame('true', $element->getAttribute('w:val')); } /** @@ -328,7 +328,7 @@ public function testDoNotTrackFormatting() $this->assertTrue($doc->elementExists($path, $file)); $element = $doc->getElement($path, $file); - $this->assertNotEquals('false', $element->getAttribute('w:val')); + $this->assertSame('true', $element->getAttribute('w:val')); } public function testAutoHyphenation() @@ -344,7 +344,7 @@ public function testAutoHyphenation() $this->assertTrue($doc->elementExists($path, $file)); $element = $doc->getElement($path, $file); - $this->assertNotEquals('false', $element->getAttribute('w:val')); + $this->assertSame('true', $element->getAttribute('w:val')); } public function testConsecutiveHyphenLimit() @@ -392,6 +392,6 @@ public function testDoNotHyphenateCaps() $this->assertTrue($doc->elementExists($path, $file)); $element = $doc->getElement($path, $file); - $this->assertNotEquals('false', $element->getAttribute('w:val')); + $this->assertSame('true', $element->getAttribute('w:val')); } } From 9ffbd98cc66d87d28cd3b80cbf9915461b5b81d4 Mon Sep 17 00:00:00 2001 From: Frank Liepert Date: Thu, 15 Feb 2018 20:12:56 +0100 Subject: [PATCH 050/135] Add missing tests --- .../Writer/Word2007/Part/SettingsTest.php | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php b/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php index 41583e375b..a8c01da010 100644 --- a/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php +++ b/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php @@ -196,6 +196,22 @@ public function testEvenAndOddHeaders() $this->assertSame('true', $element->getAttribute('w:val')); } + public function testUpdateFields() + { + $phpWord = new PhpWord(); + $phpWord->getSettings()->setUpdateFields(true); + + $doc = TestHelperDOCX::getDocument($phpWord); + + $file = 'word/settings.xml'; + + $path = '/w:settings/w:updateFields'; + $this->assertTrue($doc->elementExists($path, $file)); + + $element = $doc->getElement($path, $file); + $this->assertSame('true', $element->getAttribute('w:val')); + } + /** * Test zoom percentage */ @@ -274,6 +290,38 @@ public function testRevisionView() $this->assertEquals('true', $element->getAttribute('w:comments')); } + public function testHideSpellingErrors() + { + $phpWord = new PhpWord(); + $phpWord->getSettings()->setHideSpellingErrors(true); + + $doc = TestHelperDOCX::getDocument($phpWord); + + $file = 'word/settings.xml'; + + $path = '/w:settings/w:hideSpellingErrors'; + $this->assertTrue($doc->elementExists($path, $file)); + + $element = $doc->getElement($path, $file); + $this->assertSame('true', $element->getAttribute('w:val')); + } + + public function testHideGrammaticalErrors() + { + $phpWord = new PhpWord(); + $phpWord->getSettings()->setHideGrammaticalErrors(true); + + $doc = TestHelperDOCX::getDocument($phpWord); + + $file = 'word/settings.xml'; + + $path = '/w:settings/w:hideGrammaticalErrors'; + $this->assertTrue($doc->elementExists($path, $file)); + + $element = $doc->getElement($path, $file); + $this->assertSame('true', $element->getAttribute('w:val')); + } + /** * Test track Revisions */ From d8f4a28b94ade126a66bed836050246af2cb7ee8 Mon Sep 17 00:00:00 2001 From: Frank Liepert Date: Wed, 7 Mar 2018 20:04:19 +0100 Subject: [PATCH 051/135] Make Composer scripts compatible with Windows Windows does not like the "./" syntax --- composer.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index d1c35b40f4..742e4bc8b4 100644 --- a/composer.json +++ b/composer.json @@ -36,19 +36,19 @@ ], "scripts": { "test": [ - "./vendor/bin/phpunit --color=always" + "phpunit --color=always" ], "test-no-coverage": [ - "./vendor/bin/phpunit --color=always --no-coverage" + "phpunit --color=always --no-coverage" ], "check": [ - "./vendor/bin/php-cs-fixer fix --ansi --dry-run --diff", - "./vendor/bin/phpcs --report-width=200 --report-summary --report-full samples/ src/ tests/ --ignore=src/PhpWord/Shared/PCLZip --standard=PSR2 -n", - "./vendor/bin/phpmd src/,tests/ text ./phpmd.xml.dist --exclude pclzip.lib.php", + "php-cs-fixer fix --ansi --dry-run --diff", + "phpcs --report-width=200 --report-summary --report-full samples/ src/ tests/ --ignore=src/PhpWord/Shared/PCLZip --standard=PSR2 -n", + "phpmd src/,tests/ text ./phpmd.xml.dist --exclude pclzip.lib.php", "@test" ], "fix": [ - "./vendor/bin/php-cs-fixer fix --ansi" + "php-cs-fixer fix --ansi" ] }, "scripts-descriptions": { From eb6900969ffbce2838c1b35d1e25c9d31fc29752 Mon Sep 17 00:00:00 2001 From: Francisco Lucas Sens Date: Thu, 8 Mar 2018 16:15:31 -0300 Subject: [PATCH 052/135] Added new constant to Brazilian portuguese language --- src/PhpWord/Style/Language.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/PhpWord/Style/Language.php b/src/PhpWord/Style/Language.php index e09421e05e..c8152f5023 100644 --- a/src/PhpWord/Style/Language.php +++ b/src/PhpWord/Style/Language.php @@ -59,6 +59,9 @@ final class Language extends AbstractStyle const HI_IN = 'hi-IN'; const HI_IN_ID = 1081; + const PT_BR = 'pt-BR'; + const PT_BR_ID = 1046; + /** * Language ID, used for RTF document generation * From f9a05547f717e9c95fa2054f12d9f3fa6a56c4dd Mon Sep 17 00:00:00 2001 From: Henri MEDOT Date: Thu, 8 Mar 2018 23:46:22 +0100 Subject: [PATCH 053/135] Added support for Floating Table Positioning (tblpPr) (#639) Added support for Floating Table Positioning (tblpPr) --- CHANGELOG.md | 1 + docs/elements.rst | 1 + docs/styles.rst | 14 + samples/Sample_09_Tables.php | 12 + samples/Sample_26_Html.php | 3 + src/PhpWord/Reader/Word2007/AbstractPart.php | 30 ++ src/PhpWord/Style/Table.php | 30 ++ src/PhpWord/Style/TablePosition.php | 410 ++++++++++++++++++ src/PhpWord/Writer/Word2007/Style/Table.php | 5 + .../Writer/Word2007/Style/TablePosition.php | 65 +++ tests/PhpWord/Reader/Word2007/StyleTest.php | 35 +- tests/PhpWord/Style/TablePositionTest.php | 65 +++ tests/PhpWord/Style/TableTest.php | 13 + .../Writer/Word2007/Style/TableTest.php | 42 ++ 14 files changed, 725 insertions(+), 1 deletion(-) create mode 100644 src/PhpWord/Style/TablePosition.php create mode 100644 src/PhpWord/Writer/Word2007/Style/TablePosition.php create mode 100644 tests/PhpWord/Style/TablePositionTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index cdc4d67cd4..0c83ac35aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ v0.15.0 (?? ??? 2018) - Added support for Vertically Raised or Lowered Text (w:position) @anrikun @troosan #640 - Add support for MACROBUTTON field @phryneas @troosan #1021 - Add support for Hyphenation @Trainmaster #1282 (Document: `autoHyphenation`, `consecutiveHyphenLimit`, `hyphenationZone`, `doNotHyphenateCaps`, Paragraph: `suppressAutoHyphens`) +- Added support for Floating Table Positioning (tblpPr) @anrikun #639 ### Fixed - Fix reading of docx default style - @troosan #1238 diff --git a/docs/elements.rst b/docs/elements.rst index 4d1b93838c..4c5ad03b70 100644 --- a/docs/elements.rst +++ b/docs/elements.rst @@ -482,6 +482,7 @@ Track changes can be set on text elements. There are 2 ways to set the change in Either by calling the `setChangeInfo()`, or by setting the `TrackChange` instance on the element with `setTrackChange()`. .. code-block:: php + $phpWord = new \PhpOffice\PhpWord\PhpWord(); // New portrait section diff --git a/docs/styles.rst b/docs/styles.rst index b4ed328d45..98088e7826 100644 --- a/docs/styles.rst +++ b/docs/styles.rst @@ -108,6 +108,20 @@ Available Table style options: - ``unit``. The unit to use for the width. One of ``\PhpOffice\PhpWord\SimpleType\TblWidth``. Defaults to *auto*. - ``layout``. Table layout, either *fixed* or *autofit* See ``\PhpOffice\PhpWord\Style\Table`` for constants. - ``cellSpacing`` Cell spacing in *twip* +- ``position`` Floating Table Positioning, see below for options + +Floating Table Positioning options: + +- ``leftFromText`` Distance From Left of Table to Text in *twip* +- ``rightFromText`` Distance From Right of Table to Text in *twip* +- ``topFromText`` Distance From Top of Table to Text in *twip* +- ``bottomFromText`` Distance From Top of Table to Text in *twip* +- ``vertAnchor`` Table Vertical Anchor, one of ``\PhpOffice\PhpWord\Style\TablePosition::VANCHOR_*`` +- ``horzAnchor`` Table Horizontal Anchor, one of ``\PhpOffice\PhpWord\Style\TablePosition::HANCHOR_*`` +- ``tblpXSpec`` Relative Horizontal Alignment From Anchor, one of ``\PhpOffice\PhpWord\Style\TablePosition::XALIGN_*`` +- ``tblpX`` Absolute Horizontal Distance From Anchorin *twip* +- ``tblpYSpec`` Relative Vertical Alignment From Anchor, one of ``\PhpOffice\PhpWord\Style\TablePosition::YALIGN_*`` +- ``tblpY`` Absolute Vertical Distance From Anchorin *twip* Available Row style options: diff --git a/samples/Sample_09_Tables.php b/samples/Sample_09_Tables.php index ba41aa5484..e458a5eee0 100644 --- a/samples/Sample_09_Tables.php +++ b/samples/Sample_09_Tables.php @@ -1,4 +1,7 @@ addTable(array('alignment' => \PhpOffice\PhpWord\SimpleType\JcTable::CENTER))->addRow()->addCell(); $innerCell->addText('Inside nested table'); +// 6. Table with floating position + +$section->addTextBreak(2); +$section->addText('Table with floating positioning.', $header); + +$table = $section->addTable(array('borderSize' => 6, 'borderColor' => '999999', 'position' => array('vertAnchor' => TablePosition::VANCHOR_TEXT, 'bottomFromText' => Converter::cmToTwip(1)))); +$cell = $table->addRow()->addCell(); +$cell->addText('This is a single cell.'); + // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); if (!CLI) { diff --git a/samples/Sample_26_Html.php b/samples/Sample_26_Html.php index f608635792..31e5984f71 100644 --- a/samples/Sample_26_Html.php +++ b/samples/Sample_26_Html.php @@ -4,6 +4,7 @@ // New Word Document echo date('H:i:s') , ' Create new PhpWord object' , EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); +$phpWord->addParagraphStyle('Heading2', array('alignment' => 'center')); $section = $phpWord->addSection(); $html = '

      Adding element via HTML

      '; @@ -17,6 +18,8 @@ $html .= '

      Unordered (bulleted) list:

      '; $html .= '
      • Item 1
      • Item 2
        • Item 2.1
        • Item 2.1
      '; +$html .= '

      centered title

      '; + $html .= '

      Ordered (numbered) list:

      '; $html .= '
      1. List 1 item 1

      2. diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 2cbfba37cc..7ba53ad18d 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -462,12 +462,42 @@ protected function readTableStyle(XMLReader $xmlReader, \DOMElement $domNode) $styleDefs['layout'] = array(self::READ_VALUE, 'w:tblLayout', 'w:type'); $styleDefs['cellSpacing'] = array(self::READ_VALUE, 'w:tblCellSpacing', 'w:w'); $style = $this->readStyleDefs($xmlReader, $styleNode, $styleDefs); + + $tablePositionNode = $xmlReader->getElement('w:tblpPr', $styleNode); + if ($tablePositionNode !== null) { + $style['position'] = $this->readTablePosition($xmlReader, $tablePositionNode); + } } } return $style; } + /** + * Read w:tblpPr + * + * @param \PhpOffice\Common\XMLReader $xmlReader + * @param \DOMElement $domNode + * @return array + */ + private function readTablePosition(XMLReader $xmlReader, \DOMElement $domNode) + { + $styleDefs = array( + 'leftFromText' => array(self::READ_VALUE, '.', 'w:leftFromText'), + 'rightFromText' => array(self::READ_VALUE, '.', 'w:rightFromText'), + 'topFromText' => array(self::READ_VALUE, '.', 'w:topFromText'), + 'bottomFromText' => array(self::READ_VALUE, '.', 'w:bottomFromText'), + 'vertAnchor' => array(self::READ_VALUE, '.', 'w:vertAnchor'), + 'horzAnchor' => array(self::READ_VALUE, '.', 'w:horzAnchor'), + 'tblpXSpec' => array(self::READ_VALUE, '.', 'w:tblpXSpec'), + 'tblpX' => array(self::READ_VALUE, '.', 'w:tblpX'), + 'tblpYSpec' => array(self::READ_VALUE, '.', 'w:tblpYSpec'), + 'tblpY' => array(self::READ_VALUE, '.', 'w:tblpY'), + ); + + return $this->readStyleDefs($xmlReader, $domNode, $styleDefs); + } + /** * Read w:tcPr * diff --git a/src/PhpWord/Style/Table.php b/src/PhpWord/Style/Table.php index 8aba172a05..92a24ddec9 100644 --- a/src/PhpWord/Style/Table.php +++ b/src/PhpWord/Style/Table.php @@ -152,6 +152,13 @@ class Table extends Border */ private $layout = self::LAYOUT_AUTO; + /** + * Position + * + * @var \PhpOffice\PhpWord\Style\TablePosition + */ + private $position; + /** * Create new table style * @@ -694,4 +701,27 @@ private function setTableOnlyProperty($property, $value, $isNumeric = true) return $this; } + + /** + * Get position + * + * @return \PhpOffice\PhpWord\Style\TablePosition + */ + public function getPosition() + { + return $this->position; + } + + /** + * Set position + * + * @param mixed $value + * @return self + */ + public function setPosition($value = null) + { + $this->setObjectVal($value, 'TablePosition', $this->position); + + return $this; + } } diff --git a/src/PhpWord/Style/TablePosition.php b/src/PhpWord/Style/TablePosition.php new file mode 100644 index 0000000000..7cb0a0be16 --- /dev/null +++ b/src/PhpWord/Style/TablePosition.php @@ -0,0 +1,410 @@ +setStyleByArray($style); + } + + /** + * Get distance from left of table to text + * + * @return int + */ + public function getLeftFromText() + { + return $this->leftFromText; + } + + /** + * Set distance from left of table to text + * + * @param int $value + * @return self + */ + public function setLeftFromText($value = null) + { + $this->leftFromText = $this->setNumericVal($value, $this->leftFromText); + + return $this; + } + + /** + * Get distance from right of table to text + * + * @return int + */ + public function getRightFromText() + { + return $this->rightFromText; + } + + /** + * Set distance from right of table to text + * + * @param int $value + * @return self + */ + public function setRightFromText($value = null) + { + $this->rightFromText = $this->setNumericVal($value, $this->rightFromText); + + return $this; + } + + /** + * Get distance from top of table to text + * + * @return int + */ + public function getTopFromText() + { + return $this->topFromText; + } + + /** + * Set distance from top of table to text + * + * @param int $value + * @return self + */ + public function setTopFromText($value = null) + { + $this->topFromText = $this->setNumericVal($value, $this->topFromText); + + return $this; + } + + /** + * Get distance from bottom of table to text + * + * @return int + */ + public function getBottomFromText() + { + return $this->bottomFromText; + } + + /** + * Set distance from bottom of table to text + * + * @param int $value + * @return self + */ + public function setBottomFromText($value = null) + { + $this->bottomFromText = $this->setNumericVal($value, $this->bottomFromText); + + return $this; + } + + /** + * Get table vertical anchor + * + * @return string + */ + public function getVertAnchor() + { + return $this->vertAnchor; + } + + /** + * Set table vertical anchor + * + * @param string $value + * @return self + */ + public function setVertAnchor($value = null) + { + $enum = array( + self::VANCHOR_TEXT, + self::VANCHOR_MARGIN, + self::VANCHOR_PAGE, + ); + $this->vertAnchor = $this->setEnumVal($value, $enum, $this->vertAnchor); + + return $this; + } + + /** + * Get table horizontal anchor + * + * @return string + */ + public function getHorzAnchor() + { + return $this->horzAnchor; + } + + /** + * Set table horizontal anchor + * + * @param string $value + * @return self + */ + public function setHorzAnchor($value = null) + { + $enum = array( + self::HANCHOR_TEXT, + self::HANCHOR_MARGIN, + self::HANCHOR_PAGE, + ); + $this->horzAnchor = $this->setEnumVal($value, $enum, $this->horzAnchor); + + return $this; + } + + /** + * Get relative horizontal alignment from anchor + * + * @return string + */ + public function getTblpXSpec() + { + return $this->tblpXSpec; + } + + /** + * Set relative horizontal alignment from anchor + * + * @param string $value + * @return self + */ + public function setTblpXSpec($value = null) + { + $enum = array( + self::XALIGN_LEFT, + self::XALIGN_CENTER, + self::XALIGN_RIGHT, + self::XALIGN_INSIDE, + self::XALIGN_OUTSIDE, + ); + $this->tblpXSpec = $this->setEnumVal($value, $enum, $this->tblpXSpec); + + return $this; + } + + /** + * Get absolute horizontal distance from anchor + * + * @return int + */ + public function getTblpX() + { + return $this->tblpX; + } + + /** + * Set absolute horizontal distance from anchor + * + * @param int $value + * @return self + */ + public function setTblpX($value = null) + { + $this->tblpX = $this->setNumericVal($value, $this->tblpX); + + return $this; + } + + /** + * Get relative vertical alignment from anchor + * + * @return string + */ + public function getTblpYSpec() + { + return $this->tblpYSpec; + } + + /** + * Set relative vertical alignment from anchor + * + * @param string $value + * @return self + */ + public function setTblpYSpec($value = null) + { + $enum = array( + self::YALIGN_INLINE, + self::YALIGN_TOP, + self::YALIGN_CENTER, + self::YALIGN_BOTTOM, + self::YALIGN_INSIDE, + self::YALIGN_OUTSIDE, + ); + $this->tblpYSpec = $this->setEnumVal($value, $enum, $this->tblpYSpec); + + return $this; + } + + /** + * Get absolute vertical distance from anchor + * + * @return int + */ + public function getTblpY() + { + return $this->tblpY; + } + + /** + * Set absolute vertical distance from anchor + * + * @param int $value + * @return self + */ + public function setTblpY($value = null) + { + $this->tblpY = $this->setNumericVal($value, $this->tblpY); + + return $this; + } +} diff --git a/src/PhpWord/Writer/Word2007/Style/Table.php b/src/PhpWord/Writer/Word2007/Style/Table.php index 1422621251..058e60e2ae 100644 --- a/src/PhpWord/Writer/Word2007/Style/Table.php +++ b/src/PhpWord/Writer/Word2007/Style/Table.php @@ -80,6 +80,11 @@ private function writeStyle(XMLWriter $xmlWriter, TableStyle $style) $this->writeTblWidth($xmlWriter, 'w:tblW', $style->getUnit(), $style->getWidth()); $this->writeTblWidth($xmlWriter, 'w:tblCellSpacing', TblWidth::TWIP, $style->getCellSpacing()); $this->writeLayout($xmlWriter, $style->getLayout()); + + // Position + $styleWriter = new TablePosition($xmlWriter, $style->getPosition()); + $styleWriter->write(); + $this->writeMargin($xmlWriter, $style); $this->writeBorder($xmlWriter, $style); diff --git a/src/PhpWord/Writer/Word2007/Style/TablePosition.php b/src/PhpWord/Writer/Word2007/Style/TablePosition.php new file mode 100644 index 0000000000..14fa6a0d58 --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Style/TablePosition.php @@ -0,0 +1,65 @@ +getStyle(); + if (!$style instanceof \PhpOffice\PhpWord\Style\TablePosition) { + return; + } + + $values = array(); + $properties = array( + 'leftFromText', + 'rightFromText', + 'topFromText', + 'bottomFromText', + 'vertAnchor', + 'horzAnchor', + 'tblpXSpec', + 'tblpX', + 'tblpYSpec', + 'tblpY', + ); + foreach ($properties as $property) { + $method = 'get' . $property; + if (method_exists($style, $method)) { + $values[$property] = $style->$method(); + } + } + $values = array_filter($values); + + if ($values) { + $xmlWriter = $this->getXmlWriter(); + $xmlWriter->startElement('w:tblpPr'); + foreach ($values as $property => $value) { + $xmlWriter->writeAttribute('w:' . $property, $value); + } + $xmlWriter->endElement(); + } + } +} diff --git a/tests/PhpWord/Reader/Word2007/StyleTest.php b/tests/PhpWord/Reader/Word2007/StyleTest.php index 93e4a1f048..3b04b6770a 100644 --- a/tests/PhpWord/Reader/Word2007/StyleTest.php +++ b/tests/PhpWord/Reader/Word2007/StyleTest.php @@ -20,6 +20,7 @@ use PhpOffice\PhpWord\AbstractTestReader; use PhpOffice\PhpWord\SimpleType\TblWidth; use PhpOffice\PhpWord\Style\Table; +use PhpOffice\PhpWord\Style\TablePosition; /** * Test class for PhpOffice\PhpWord\Reader\Word2007\Styles @@ -61,12 +62,44 @@ public function testReadCellSpacing() $elements = $phpWord->getSection(0)->getElements(); $this->assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]); $this->assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle()); - $this->assertEquals(TblWidth::AUTO, $elements[0]->getStyle()->getUnit()); /** @var \PhpOffice\PhpWord\Style\Table $tableStyle */ $tableStyle = $elements[0]->getStyle(); + $this->assertEquals(TblWidth::AUTO, $tableStyle->getUnit()); $this->assertEquals(10.5, $tableStyle->getCellSpacing()); } + /** + * Test reading of table position + */ + public function testReadTablePosition() + { + $documentXml = ' + + + + '; + + $phpWord = $this->getDocumentFromString(array('document' => $documentXml)); + + $elements = $phpWord->getSection(0)->getElements(); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]); + $this->assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle()); + $this->assertNotNull($elements[0]->getStyle()->getPosition()); + $this->assertInstanceOf('PhpOffice\PhpWord\Style\TablePosition', $elements[0]->getStyle()->getPosition()); + /** @var \PhpOffice\PhpWord\Style\TablePosition $tableStyle */ + $tableStyle = $elements[0]->getStyle()->getPosition(); + $this->assertEquals(10, $tableStyle->getLeftFromText()); + $this->assertEquals(20, $tableStyle->getRightFromText()); + $this->assertEquals(30, $tableStyle->getTopFromText()); + $this->assertEquals(40, $tableStyle->getBottomFromText()); + $this->assertEquals(TablePosition::VANCHOR_PAGE, $tableStyle->getVertAnchor()); + $this->assertEquals(TablePosition::HANCHOR_MARGIN, $tableStyle->getHorzAnchor()); + $this->assertEquals(TablePosition::XALIGN_CENTER, $tableStyle->getTblpXSpec()); + $this->assertEquals(50, $tableStyle->getTblpX()); + $this->assertEquals(TablePosition::YALIGN_TOP, $tableStyle->getTblpYSpec()); + $this->assertEquals(60, $tableStyle->getTblpY()); + } + /** * Test reading of position */ diff --git a/tests/PhpWord/Style/TablePositionTest.php b/tests/PhpWord/Style/TablePositionTest.php new file mode 100644 index 0000000000..77b22e4e14 --- /dev/null +++ b/tests/PhpWord/Style/TablePositionTest.php @@ -0,0 +1,65 @@ + TablePosition::VANCHOR_PAGE, 'bottomFromText' => 20); + + $object = new TablePosition($styleTable); + $this->assertEquals(TablePosition::VANCHOR_PAGE, $object->getVertAnchor()); + $this->assertEquals(20, $object->getBottomFromText()); + } + + /** + * Test setting style with normal value + */ + public function testSetGetNormal() + { + $object = new TablePosition(); + + $attributes = array( + 'leftFromText' => 4, + 'rightFromText' => 4, + 'topFromText' => 4, + 'bottomFromText' => 4, + 'vertAnchor' => TablePosition::VANCHOR_PAGE, + 'horzAnchor' => TablePosition::HANCHOR_TEXT, + 'tblpXSpec' => TablePosition::XALIGN_CENTER, + 'tblpX' => 5, + 'tblpYSpec' => TablePosition::YALIGN_OUTSIDE, + 'tblpY' => 6, + ); + foreach ($attributes as $key => $value) { + $set = "set{$key}"; + $get = "get{$key}"; + $object->$set($value); + $this->assertEquals($value, $object->$get()); + } + } +} diff --git a/tests/PhpWord/Style/TableTest.php b/tests/PhpWord/Style/TableTest.php index 9dec422e97..1ee718df68 100644 --- a/tests/PhpWord/Style/TableTest.php +++ b/tests/PhpWord/Style/TableTest.php @@ -195,4 +195,17 @@ public function testTableCellSpacing() $object = new Table(array('cellSpacing' => 20)); $this->assertEquals(20, $object->getCellSpacing()); } + + /** + * Tests table floating position + */ + public function testTablePosition() + { + $object = new Table(); + $this->assertNull($object->getPosition()); + + $object->setPosition(array('vertAnchor' => TablePosition::VANCHOR_PAGE)); + $this->assertNotNull($object->getPosition()); + $this->assertEquals(TablePosition::VANCHOR_PAGE, $object->getPosition()->getVertAnchor()); + } } diff --git a/tests/PhpWord/Writer/Word2007/Style/TableTest.php b/tests/PhpWord/Writer/Word2007/Style/TableTest.php index c0a0b3ad13..2b67507a94 100644 --- a/tests/PhpWord/Writer/Word2007/Style/TableTest.php +++ b/tests/PhpWord/Writer/Word2007/Style/TableTest.php @@ -18,6 +18,7 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Style; use PhpOffice\PhpWord\Style\Table; +use PhpOffice\PhpWord\Style\TablePosition; use PhpOffice\PhpWord\TestHelperDOCX; /** @@ -76,4 +77,45 @@ public function testCellSpacing() $this->assertEquals(10.3, $doc->getElementAttribute($path, 'w:w')); $this->assertEquals(\PhpOffice\PhpWord\SimpleType\TblWidth::TWIP, $doc->getElementAttribute($path, 'w:type')); } + + /** + * Test write table position + */ + public function testTablePosition() + { + $tablePosition = array( + 'leftFromText' => 10, + 'rightFromText' => 20, + 'topFromText' => 30, + 'bottomFromText' => 40, + 'vertAnchor' => TablePosition::VANCHOR_PAGE, + 'horzAnchor' => TablePosition::HANCHOR_MARGIN, + 'tblpXSpec' => TablePosition::XALIGN_CENTER, + 'tblpX' => 50, + 'tblpYSpec' => TablePosition::YALIGN_TOP, + 'tblpY' => 60, + ); + $tableStyle = new Table(); + $tableStyle->setPosition($tablePosition); + + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + $table = $section->addTable($tableStyle); + $table->addRow(); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $path = '/w:document/w:body/w:tbl/w:tblPr/w:tblpPr'; + $this->assertTrue($doc->elementExists($path)); + $this->assertEquals(10, $doc->getElementAttribute($path, 'w:leftFromText')); + $this->assertEquals(20, $doc->getElementAttribute($path, 'w:rightFromText')); + $this->assertEquals(30, $doc->getElementAttribute($path, 'w:topFromText')); + $this->assertEquals(40, $doc->getElementAttribute($path, 'w:bottomFromText')); + $this->assertEquals(TablePosition::VANCHOR_PAGE, $doc->getElementAttribute($path, 'w:vertAnchor')); + $this->assertEquals(TablePosition::HANCHOR_MARGIN, $doc->getElementAttribute($path, 'w:horzAnchor')); + $this->assertEquals(TablePosition::XALIGN_CENTER, $doc->getElementAttribute($path, 'w:tblpXSpec')); + $this->assertEquals(50, $doc->getElementAttribute($path, 'w:tblpX')); + $this->assertEquals(TablePosition::YALIGN_TOP, $doc->getElementAttribute($path, 'w:tblpYSpec')); + $this->assertEquals(60, $doc->getElementAttribute($path, 'w:tblpY')); + } } From 77f2b16bc1b7ddfed894b8f6129be3456fa78326 Mon Sep 17 00:00:00 2001 From: troosan Date: Thu, 8 Mar 2018 23:52:25 +0100 Subject: [PATCH 054/135] update copyright to 2018 --- bootstrap.php | 2 +- src/PhpWord/Collection/AbstractCollection.php | 2 +- src/PhpWord/Collection/Bookmarks.php | 2 +- src/PhpWord/Collection/Charts.php | 2 +- src/PhpWord/Collection/Comments.php | 2 +- src/PhpWord/Collection/Endnotes.php | 2 +- src/PhpWord/Collection/Footnotes.php | 2 +- src/PhpWord/Collection/Titles.php | 2 +- src/PhpWord/ComplexType/FootnoteProperties.php | 2 +- src/PhpWord/ComplexType/ProofState.php | 2 +- src/PhpWord/ComplexType/TrackChangesView.php | 2 +- src/PhpWord/Element/AbstractContainer.php | 2 +- src/PhpWord/Element/AbstractElement.php | 2 +- src/PhpWord/Element/Bookmark.php | 2 +- src/PhpWord/Element/Cell.php | 2 +- src/PhpWord/Element/Chart.php | 2 +- src/PhpWord/Element/CheckBox.php | 2 +- src/PhpWord/Element/Comment.php | 2 +- src/PhpWord/Element/Endnote.php | 2 +- src/PhpWord/Element/Field.php | 2 +- src/PhpWord/Element/Footer.php | 2 +- src/PhpWord/Element/Footnote.php | 2 +- src/PhpWord/Element/FormField.php | 2 +- src/PhpWord/Element/Header.php | 2 +- src/PhpWord/Element/Image.php | 2 +- src/PhpWord/Element/Line.php | 2 +- src/PhpWord/Element/Link.php | 2 +- src/PhpWord/Element/ListItem.php | 2 +- src/PhpWord/Element/ListItemRun.php | 2 +- src/PhpWord/Element/OLEObject.php | 2 +- src/PhpWord/Element/PageBreak.php | 2 +- src/PhpWord/Element/PreserveText.php | 2 +- src/PhpWord/Element/Row.php | 2 +- src/PhpWord/Element/SDT.php | 2 +- src/PhpWord/Element/Section.php | 2 +- src/PhpWord/Element/Shape.php | 2 +- src/PhpWord/Element/TOC.php | 2 +- src/PhpWord/Element/Table.php | 2 +- src/PhpWord/Element/Text.php | 2 +- src/PhpWord/Element/TextBox.php | 2 +- src/PhpWord/Element/TextBreak.php | 2 +- src/PhpWord/Element/TextRun.php | 2 +- src/PhpWord/Element/Title.php | 2 +- src/PhpWord/Element/TrackChange.php | 2 +- src/PhpWord/Escaper/AbstractEscaper.php | 2 +- src/PhpWord/Escaper/EscaperInterface.php | 2 +- src/PhpWord/Escaper/RegExp.php | 2 +- src/PhpWord/Escaper/Rtf.php | 2 +- src/PhpWord/Escaper/Xml.php | 2 +- src/PhpWord/Exception/CopyFileException.php | 2 +- src/PhpWord/Exception/CreateTemporaryFileException.php | 2 +- src/PhpWord/Exception/Exception.php | 2 +- src/PhpWord/Exception/InvalidImageException.php | 2 +- src/PhpWord/Exception/InvalidObjectException.php | 2 +- src/PhpWord/Exception/InvalidStyleException.php | 2 +- src/PhpWord/Exception/UnsupportedImageTypeException.php | 2 +- src/PhpWord/IOFactory.php | 2 +- src/PhpWord/Media.php | 2 +- src/PhpWord/Metadata/Compatibility.php | 2 +- src/PhpWord/Metadata/DocInfo.php | 2 +- src/PhpWord/Metadata/Protection.php | 2 +- src/PhpWord/Metadata/Settings.php | 2 +- src/PhpWord/PhpWord.php | 2 +- src/PhpWord/Reader/AbstractReader.php | 2 +- src/PhpWord/Reader/HTML.php | 2 +- src/PhpWord/Reader/MsDoc.php | 2 +- src/PhpWord/Reader/ODText.php | 2 +- src/PhpWord/Reader/ODText/AbstractPart.php | 2 +- src/PhpWord/Reader/ODText/Content.php | 2 +- src/PhpWord/Reader/ODText/Meta.php | 2 +- src/PhpWord/Reader/RTF.php | 2 +- src/PhpWord/Reader/RTF/Document.php | 2 +- src/PhpWord/Reader/ReaderInterface.php | 2 +- src/PhpWord/Reader/Word2007.php | 2 +- src/PhpWord/Reader/Word2007/AbstractPart.php | 2 +- src/PhpWord/Reader/Word2007/DocPropsApp.php | 2 +- src/PhpWord/Reader/Word2007/DocPropsCore.php | 2 +- src/PhpWord/Reader/Word2007/DocPropsCustom.php | 2 +- src/PhpWord/Reader/Word2007/Document.php | 2 +- src/PhpWord/Reader/Word2007/Endnotes.php | 2 +- src/PhpWord/Reader/Word2007/Footnotes.php | 2 +- src/PhpWord/Reader/Word2007/Numbering.php | 2 +- src/PhpWord/Reader/Word2007/Settings.php | 2 +- src/PhpWord/Reader/Word2007/Styles.php | 2 +- src/PhpWord/Settings.php | 2 +- src/PhpWord/Shared/AbstractEnum.php | 2 +- src/PhpWord/Shared/Converter.php | 2 +- src/PhpWord/Shared/Html.php | 2 +- src/PhpWord/Shared/Microsoft/PasswordEncoder.php | 2 +- src/PhpWord/Shared/OLERead.php | 2 +- src/PhpWord/Shared/ZipArchive.php | 2 +- src/PhpWord/SimpleType/DocProtect.php | 2 +- src/PhpWord/SimpleType/Jc.php | 2 +- src/PhpWord/SimpleType/JcTable.php | 2 +- src/PhpWord/SimpleType/LineSpacingRule.php | 2 +- src/PhpWord/SimpleType/NumberFormat.php | 2 +- src/PhpWord/SimpleType/TblWidth.php | 2 +- src/PhpWord/SimpleType/TextAlignment.php | 2 +- src/PhpWord/SimpleType/Zoom.php | 2 +- src/PhpWord/Style.php | 2 +- src/PhpWord/Style/AbstractStyle.php | 2 +- src/PhpWord/Style/Border.php | 2 +- src/PhpWord/Style/Cell.php | 2 +- src/PhpWord/Style/Chart.php | 2 +- src/PhpWord/Style/Extrusion.php | 2 +- src/PhpWord/Style/Fill.php | 2 +- src/PhpWord/Style/Font.php | 2 +- src/PhpWord/Style/Frame.php | 2 +- src/PhpWord/Style/Image.php | 2 +- src/PhpWord/Style/Indentation.php | 2 +- src/PhpWord/Style/Language.php | 2 +- src/PhpWord/Style/Line.php | 2 +- src/PhpWord/Style/LineNumbering.php | 2 +- src/PhpWord/Style/ListItem.php | 2 +- src/PhpWord/Style/Numbering.php | 2 +- src/PhpWord/Style/NumberingLevel.php | 2 +- src/PhpWord/Style/Outline.php | 2 +- src/PhpWord/Style/Paper.php | 2 +- src/PhpWord/Style/Paragraph.php | 2 +- src/PhpWord/Style/Row.php | 2 +- src/PhpWord/Style/Section.php | 2 +- src/PhpWord/Style/Shading.php | 2 +- src/PhpWord/Style/Shadow.php | 2 +- src/PhpWord/Style/Shape.php | 2 +- src/PhpWord/Style/Spacing.php | 2 +- src/PhpWord/Style/TOC.php | 2 +- src/PhpWord/Style/Tab.php | 2 +- src/PhpWord/Style/Table.php | 2 +- src/PhpWord/Style/TablePosition.php | 2 +- src/PhpWord/Style/TextBox.php | 2 +- src/PhpWord/Template.php | 2 +- src/PhpWord/TemplateProcessor.php | 2 +- src/PhpWord/Writer/AbstractWriter.php | 2 +- src/PhpWord/Writer/HTML.php | 2 +- src/PhpWord/Writer/HTML/Element/AbstractElement.php | 2 +- src/PhpWord/Writer/HTML/Element/Bookmark.php | 2 +- src/PhpWord/Writer/HTML/Element/Container.php | 2 +- src/PhpWord/Writer/HTML/Element/Endnote.php | 2 +- src/PhpWord/Writer/HTML/Element/Footnote.php | 2 +- src/PhpWord/Writer/HTML/Element/Image.php | 2 +- src/PhpWord/Writer/HTML/Element/Link.php | 2 +- src/PhpWord/Writer/HTML/Element/ListItem.php | 2 +- src/PhpWord/Writer/HTML/Element/PageBreak.php | 2 +- src/PhpWord/Writer/HTML/Element/Table.php | 2 +- src/PhpWord/Writer/HTML/Element/Text.php | 2 +- src/PhpWord/Writer/HTML/Element/TextBreak.php | 2 +- src/PhpWord/Writer/HTML/Element/TextRun.php | 2 +- src/PhpWord/Writer/HTML/Element/Title.php | 2 +- src/PhpWord/Writer/HTML/Part/AbstractPart.php | 2 +- src/PhpWord/Writer/HTML/Part/Body.php | 2 +- src/PhpWord/Writer/HTML/Part/Head.php | 2 +- src/PhpWord/Writer/HTML/Style/AbstractStyle.php | 2 +- src/PhpWord/Writer/HTML/Style/Font.php | 2 +- src/PhpWord/Writer/HTML/Style/Generic.php | 2 +- src/PhpWord/Writer/HTML/Style/Image.php | 2 +- src/PhpWord/Writer/HTML/Style/Paragraph.php | 2 +- src/PhpWord/Writer/ODText.php | 2 +- src/PhpWord/Writer/ODText/Element/AbstractElement.php | 2 +- src/PhpWord/Writer/ODText/Element/Container.php | 2 +- src/PhpWord/Writer/ODText/Element/Image.php | 2 +- src/PhpWord/Writer/ODText/Element/Link.php | 2 +- src/PhpWord/Writer/ODText/Element/PageBreak.php | 2 +- src/PhpWord/Writer/ODText/Element/Table.php | 2 +- src/PhpWord/Writer/ODText/Element/Text.php | 2 +- src/PhpWord/Writer/ODText/Element/TextBreak.php | 2 +- src/PhpWord/Writer/ODText/Element/TextRun.php | 2 +- src/PhpWord/Writer/ODText/Element/Title.php | 2 +- src/PhpWord/Writer/ODText/Part/AbstractPart.php | 2 +- src/PhpWord/Writer/ODText/Part/Content.php | 2 +- src/PhpWord/Writer/ODText/Part/Manifest.php | 2 +- src/PhpWord/Writer/ODText/Part/Meta.php | 2 +- src/PhpWord/Writer/ODText/Part/Mimetype.php | 2 +- src/PhpWord/Writer/ODText/Part/Styles.php | 2 +- src/PhpWord/Writer/ODText/Style/AbstractStyle.php | 2 +- src/PhpWord/Writer/ODText/Style/Font.php | 2 +- src/PhpWord/Writer/ODText/Style/Image.php | 2 +- src/PhpWord/Writer/ODText/Style/Paragraph.php | 2 +- src/PhpWord/Writer/ODText/Style/Section.php | 2 +- src/PhpWord/Writer/ODText/Style/Table.php | 2 +- src/PhpWord/Writer/PDF.php | 2 +- src/PhpWord/Writer/PDF/AbstractRenderer.php | 2 +- src/PhpWord/Writer/PDF/DomPDF.php | 2 +- src/PhpWord/Writer/PDF/MPDF.php | 2 +- src/PhpWord/Writer/PDF/TCPDF.php | 2 +- src/PhpWord/Writer/RTF.php | 2 +- src/PhpWord/Writer/RTF/Element/AbstractElement.php | 2 +- src/PhpWord/Writer/RTF/Element/Container.php | 2 +- src/PhpWord/Writer/RTF/Element/Image.php | 2 +- src/PhpWord/Writer/RTF/Element/Link.php | 2 +- src/PhpWord/Writer/RTF/Element/ListItem.php | 2 +- src/PhpWord/Writer/RTF/Element/PageBreak.php | 2 +- src/PhpWord/Writer/RTF/Element/Table.php | 2 +- src/PhpWord/Writer/RTF/Element/Text.php | 2 +- src/PhpWord/Writer/RTF/Element/TextBreak.php | 2 +- src/PhpWord/Writer/RTF/Element/TextRun.php | 2 +- src/PhpWord/Writer/RTF/Element/Title.php | 2 +- src/PhpWord/Writer/RTF/Part/AbstractPart.php | 2 +- src/PhpWord/Writer/RTF/Part/Document.php | 2 +- src/PhpWord/Writer/RTF/Part/Header.php | 2 +- src/PhpWord/Writer/RTF/Style/AbstractStyle.php | 2 +- src/PhpWord/Writer/RTF/Style/Border.php | 2 +- src/PhpWord/Writer/RTF/Style/Font.php | 2 +- src/PhpWord/Writer/RTF/Style/Paragraph.php | 2 +- src/PhpWord/Writer/RTF/Style/Section.php | 2 +- src/PhpWord/Writer/Word2007.php | 2 +- src/PhpWord/Writer/Word2007/Element/AbstractElement.php | 2 +- src/PhpWord/Writer/Word2007/Element/Bookmark.php | 2 +- src/PhpWord/Writer/Word2007/Element/Chart.php | 2 +- src/PhpWord/Writer/Word2007/Element/CheckBox.php | 2 +- src/PhpWord/Writer/Word2007/Element/Container.php | 2 +- src/PhpWord/Writer/Word2007/Element/Endnote.php | 2 +- src/PhpWord/Writer/Word2007/Element/Field.php | 2 +- src/PhpWord/Writer/Word2007/Element/Footnote.php | 2 +- src/PhpWord/Writer/Word2007/Element/FormField.php | 2 +- src/PhpWord/Writer/Word2007/Element/Image.php | 2 +- src/PhpWord/Writer/Word2007/Element/Line.php | 2 +- src/PhpWord/Writer/Word2007/Element/Link.php | 2 +- src/PhpWord/Writer/Word2007/Element/ListItem.php | 2 +- src/PhpWord/Writer/Word2007/Element/ListItemRun.php | 2 +- src/PhpWord/Writer/Word2007/Element/OLEObject.php | 2 +- src/PhpWord/Writer/Word2007/Element/PageBreak.php | 2 +- src/PhpWord/Writer/Word2007/Element/ParagraphAlignment.php | 2 +- src/PhpWord/Writer/Word2007/Element/PreserveText.php | 2 +- src/PhpWord/Writer/Word2007/Element/SDT.php | 2 +- src/PhpWord/Writer/Word2007/Element/Shape.php | 2 +- src/PhpWord/Writer/Word2007/Element/TOC.php | 2 +- src/PhpWord/Writer/Word2007/Element/Table.php | 2 +- src/PhpWord/Writer/Word2007/Element/TableAlignment.php | 2 +- src/PhpWord/Writer/Word2007/Element/Text.php | 2 +- src/PhpWord/Writer/Word2007/Element/TextBox.php | 2 +- src/PhpWord/Writer/Word2007/Element/TextBreak.php | 2 +- src/PhpWord/Writer/Word2007/Element/TextRun.php | 2 +- src/PhpWord/Writer/Word2007/Element/Title.php | 2 +- src/PhpWord/Writer/Word2007/Part/AbstractPart.php | 2 +- src/PhpWord/Writer/Word2007/Part/Chart.php | 2 +- src/PhpWord/Writer/Word2007/Part/Comments.php | 2 +- src/PhpWord/Writer/Word2007/Part/ContentTypes.php | 2 +- src/PhpWord/Writer/Word2007/Part/DocPropsApp.php | 2 +- src/PhpWord/Writer/Word2007/Part/DocPropsCore.php | 2 +- src/PhpWord/Writer/Word2007/Part/DocPropsCustom.php | 2 +- src/PhpWord/Writer/Word2007/Part/Document.php | 2 +- src/PhpWord/Writer/Word2007/Part/Endnotes.php | 2 +- src/PhpWord/Writer/Word2007/Part/FontTable.php | 2 +- src/PhpWord/Writer/Word2007/Part/Footer.php | 2 +- src/PhpWord/Writer/Word2007/Part/Footnotes.php | 2 +- src/PhpWord/Writer/Word2007/Part/Header.php | 2 +- src/PhpWord/Writer/Word2007/Part/Numbering.php | 2 +- src/PhpWord/Writer/Word2007/Part/Rels.php | 2 +- src/PhpWord/Writer/Word2007/Part/RelsDocument.php | 2 +- src/PhpWord/Writer/Word2007/Part/RelsPart.php | 2 +- src/PhpWord/Writer/Word2007/Part/Settings.php | 2 +- src/PhpWord/Writer/Word2007/Part/Styles.php | 2 +- src/PhpWord/Writer/Word2007/Part/Theme.php | 2 +- src/PhpWord/Writer/Word2007/Part/WebSettings.php | 2 +- src/PhpWord/Writer/Word2007/Style/AbstractStyle.php | 2 +- src/PhpWord/Writer/Word2007/Style/Cell.php | 2 +- src/PhpWord/Writer/Word2007/Style/Extrusion.php | 2 +- src/PhpWord/Writer/Word2007/Style/Fill.php | 2 +- src/PhpWord/Writer/Word2007/Style/Font.php | 2 +- src/PhpWord/Writer/Word2007/Style/Frame.php | 2 +- src/PhpWord/Writer/Word2007/Style/Image.php | 2 +- src/PhpWord/Writer/Word2007/Style/Indentation.php | 2 +- src/PhpWord/Writer/Word2007/Style/Line.php | 2 +- src/PhpWord/Writer/Word2007/Style/LineNumbering.php | 2 +- src/PhpWord/Writer/Word2007/Style/MarginBorder.php | 2 +- src/PhpWord/Writer/Word2007/Style/Outline.php | 2 +- src/PhpWord/Writer/Word2007/Style/Paragraph.php | 2 +- src/PhpWord/Writer/Word2007/Style/Row.php | 2 +- src/PhpWord/Writer/Word2007/Style/Section.php | 2 +- src/PhpWord/Writer/Word2007/Style/Shading.php | 2 +- src/PhpWord/Writer/Word2007/Style/Shadow.php | 2 +- src/PhpWord/Writer/Word2007/Style/Shape.php | 2 +- src/PhpWord/Writer/Word2007/Style/Spacing.php | 2 +- src/PhpWord/Writer/Word2007/Style/Tab.php | 2 +- src/PhpWord/Writer/Word2007/Style/Table.php | 2 +- src/PhpWord/Writer/Word2007/Style/TablePosition.php | 2 +- src/PhpWord/Writer/Word2007/Style/TextBox.php | 2 +- src/PhpWord/Writer/WriterInterface.php | 2 +- tests/PhpWord/Collection/CollectionTest.php | 2 +- tests/PhpWord/ComplexType/FootnotePropertiesTest.php | 2 +- tests/PhpWord/ComplexType/ProofStateTest.php | 2 +- tests/PhpWord/Element/AbstractElementTest.php | 2 +- tests/PhpWord/Element/BookmarkTest.php | 2 +- tests/PhpWord/Element/CellTest.php | 2 +- tests/PhpWord/Element/CheckBoxTest.php | 2 +- tests/PhpWord/Element/CommentTest.php | 2 +- tests/PhpWord/Element/FieldTest.php | 2 +- tests/PhpWord/Element/FooterTest.php | 2 +- tests/PhpWord/Element/FootnoteTest.php | 2 +- tests/PhpWord/Element/HeaderTest.php | 2 +- tests/PhpWord/Element/ImageTest.php | 2 +- tests/PhpWord/Element/LineTest.php | 2 +- tests/PhpWord/Element/LinkTest.php | 2 +- tests/PhpWord/Element/ListItemRunTest.php | 2 +- tests/PhpWord/Element/ListItemTest.php | 2 +- tests/PhpWord/Element/ObjectTest.php | 2 +- tests/PhpWord/Element/PageBreakTest.php | 2 +- tests/PhpWord/Element/PreserveTextTest.php | 2 +- tests/PhpWord/Element/RowTest.php | 2 +- tests/PhpWord/Element/SDTTest.php | 2 +- tests/PhpWord/Element/SectionTest.php | 2 +- tests/PhpWord/Element/TOCTest.php | 2 +- tests/PhpWord/Element/TableTest.php | 2 +- tests/PhpWord/Element/TextBoxTest.php | 2 +- tests/PhpWord/Element/TextBreakTest.php | 2 +- tests/PhpWord/Element/TextRunTest.php | 2 +- tests/PhpWord/Element/TextTest.php | 2 +- tests/PhpWord/Element/TitleTest.php | 2 +- tests/PhpWord/Element/TrackChangeTest.php | 2 +- tests/PhpWord/Exception/CopyFileExceptionTest.php | 2 +- tests/PhpWord/Exception/CreateTemporaryFileExceptionTest.php | 2 +- tests/PhpWord/Exception/ExceptionTest.php | 2 +- tests/PhpWord/Exception/InvalidImageExceptionTest.php | 2 +- tests/PhpWord/Exception/InvalidStyleExceptionTest.php | 2 +- tests/PhpWord/Exception/UnsupportedImageTypeExceptionTest.php | 2 +- tests/PhpWord/IOFactoryTest.php | 2 +- tests/PhpWord/MediaTest.php | 2 +- tests/PhpWord/Metadata/DocInfoTest.php | 2 +- tests/PhpWord/Metadata/SettingsTest.php | 2 +- tests/PhpWord/PhpWordTest.php | 2 +- tests/PhpWord/Reader/HTMLTest.php | 2 +- tests/PhpWord/Reader/MsDocTest.php | 2 +- tests/PhpWord/Reader/ODTextTest.php | 2 +- tests/PhpWord/Reader/RTFTest.php | 2 +- tests/PhpWord/Reader/Word2007/ElementTest.php | 2 +- tests/PhpWord/Reader/Word2007/PartTest.php | 2 +- tests/PhpWord/Reader/Word2007/StyleTest.php | 2 +- tests/PhpWord/Reader/Word2007Test.php | 2 +- tests/PhpWord/SettingsTest.php | 2 +- tests/PhpWord/Shared/ConverterTest.php | 2 +- tests/PhpWord/Shared/HtmlTest.php | 2 +- tests/PhpWord/Shared/Microsoft/PasswordEncoderTest.php | 2 +- tests/PhpWord/Shared/ZipArchiveTest.php | 2 +- tests/PhpWord/Style/AbstractStyleTest.php | 2 +- tests/PhpWord/Style/CellTest.php | 2 +- tests/PhpWord/Style/FontTest.php | 2 +- tests/PhpWord/Style/ImageTest.php | 2 +- tests/PhpWord/Style/IndentationTest.php | 2 +- tests/PhpWord/Style/LanguageTest.php | 2 +- tests/PhpWord/Style/LineNumberingTest.php | 2 +- tests/PhpWord/Style/LineTest.php | 2 +- tests/PhpWord/Style/ListItemTest.php | 2 +- tests/PhpWord/Style/NumberingLevelTest.php | 2 +- tests/PhpWord/Style/NumberingTest.php | 2 +- tests/PhpWord/Style/PaperTest.php | 2 +- tests/PhpWord/Style/ParagraphTest.php | 2 +- tests/PhpWord/Style/RowTest.php | 2 +- tests/PhpWord/Style/SectionTest.php | 2 +- tests/PhpWord/Style/ShadingTest.php | 2 +- tests/PhpWord/Style/SpacingTest.php | 2 +- tests/PhpWord/Style/TOCTest.php | 2 +- tests/PhpWord/Style/TabTest.php | 2 +- tests/PhpWord/Style/TableTest.php | 2 +- tests/PhpWord/Style/TextBoxTest.php | 2 +- tests/PhpWord/StyleTest.php | 2 +- tests/PhpWord/TemplateProcessorTest.php | 2 +- tests/PhpWord/Writer/HTML/ElementTest.php | 2 +- tests/PhpWord/Writer/HTML/PartTest.php | 2 +- tests/PhpWord/Writer/HTML/StyleTest.php | 2 +- tests/PhpWord/Writer/HTMLTest.php | 2 +- tests/PhpWord/Writer/ODText/ElementTest.php | 2 +- tests/PhpWord/Writer/ODText/Part/AbstractPartTest.php | 2 +- tests/PhpWord/Writer/ODText/Part/ContentTest.php | 2 +- tests/PhpWord/Writer/ODText/StyleTest.php | 2 +- tests/PhpWord/Writer/ODTextTest.php | 2 +- tests/PhpWord/Writer/PDF/DomPDFTest.php | 2 +- tests/PhpWord/Writer/PDF/MPDFTest.php | 2 +- tests/PhpWord/Writer/PDF/TCPDFTest.php | 2 +- tests/PhpWord/Writer/PDFTest.php | 2 +- tests/PhpWord/Writer/RTF/ElementTest.php | 2 +- tests/PhpWord/Writer/RTF/StyleTest.php | 2 +- tests/PhpWord/Writer/RTFTest.php | 2 +- tests/PhpWord/Writer/Word2007/ElementTest.php | 2 +- tests/PhpWord/Writer/Word2007/Part/AbstractPartTest.php | 2 +- tests/PhpWord/Writer/Word2007/Part/CommentsTest.php | 2 +- tests/PhpWord/Writer/Word2007/Part/DocumentTest.php | 2 +- tests/PhpWord/Writer/Word2007/Part/FooterTest.php | 2 +- tests/PhpWord/Writer/Word2007/Part/FootnotesTest.php | 2 +- tests/PhpWord/Writer/Word2007/Part/HeaderTest.php | 2 +- tests/PhpWord/Writer/Word2007/Part/NumberingTest.php | 2 +- tests/PhpWord/Writer/Word2007/Part/SettingsTest.php | 2 +- tests/PhpWord/Writer/Word2007/Part/StylesTest.php | 2 +- tests/PhpWord/Writer/Word2007/PartTest.php | 2 +- tests/PhpWord/Writer/Word2007/Style/FontTest.php | 2 +- tests/PhpWord/Writer/Word2007/Style/ParagraphTest.php | 2 +- tests/PhpWord/Writer/Word2007/Style/TableTest.php | 2 +- tests/PhpWord/Writer/Word2007/StyleTest.php | 2 +- tests/PhpWord/Writer/Word2007Test.php | 2 +- tests/PhpWord/_includes/AbstractTestReader.php | 2 +- tests/PhpWord/_includes/TestHelperDOCX.php | 2 +- tests/PhpWord/_includes/XmlDocument.php | 2 +- tests/bootstrap.php | 2 +- 392 files changed, 392 insertions(+), 392 deletions(-) diff --git a/bootstrap.php b/bootstrap.php index 362e8b74e9..740e3d044c 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. test bootstrap * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Collection/AbstractCollection.php b/src/PhpWord/Collection/AbstractCollection.php index d49967cac7..899ec28756 100644 --- a/src/PhpWord/Collection/AbstractCollection.php +++ b/src/PhpWord/Collection/AbstractCollection.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Collection/Bookmarks.php b/src/PhpWord/Collection/Bookmarks.php index 7210fb034e..b5ffd5f40a 100644 --- a/src/PhpWord/Collection/Bookmarks.php +++ b/src/PhpWord/Collection/Bookmarks.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Collection/Charts.php b/src/PhpWord/Collection/Charts.php index 56d92c9411..aa807d1e58 100644 --- a/src/PhpWord/Collection/Charts.php +++ b/src/PhpWord/Collection/Charts.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Collection/Comments.php b/src/PhpWord/Collection/Comments.php index f2fe82d921..b6c02d392f 100644 --- a/src/PhpWord/Collection/Comments.php +++ b/src/PhpWord/Collection/Comments.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Collection/Endnotes.php b/src/PhpWord/Collection/Endnotes.php index 52a56d3130..db01b408db 100644 --- a/src/PhpWord/Collection/Endnotes.php +++ b/src/PhpWord/Collection/Endnotes.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Collection/Footnotes.php b/src/PhpWord/Collection/Footnotes.php index 63989f53cd..a0a31ca494 100644 --- a/src/PhpWord/Collection/Footnotes.php +++ b/src/PhpWord/Collection/Footnotes.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Collection/Titles.php b/src/PhpWord/Collection/Titles.php index 9e4f12cd60..1ea58ec0d6 100644 --- a/src/PhpWord/Collection/Titles.php +++ b/src/PhpWord/Collection/Titles.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/ComplexType/FootnoteProperties.php b/src/PhpWord/ComplexType/FootnoteProperties.php index 8cb3a869ee..e42c9f9d40 100644 --- a/src/PhpWord/ComplexType/FootnoteProperties.php +++ b/src/PhpWord/ComplexType/FootnoteProperties.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/ComplexType/ProofState.php b/src/PhpWord/ComplexType/ProofState.php index 6a915da1ba..4f8dafe3aa 100644 --- a/src/PhpWord/ComplexType/ProofState.php +++ b/src/PhpWord/ComplexType/ProofState.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/ComplexType/TrackChangesView.php b/src/PhpWord/ComplexType/TrackChangesView.php index 3fc16298c1..92ea05eab3 100644 --- a/src/PhpWord/ComplexType/TrackChangesView.php +++ b/src/PhpWord/ComplexType/TrackChangesView.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/AbstractContainer.php b/src/PhpWord/Element/AbstractContainer.php index 1cedbef01f..ec990720f5 100644 --- a/src/PhpWord/Element/AbstractContainer.php +++ b/src/PhpWord/Element/AbstractContainer.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/AbstractElement.php b/src/PhpWord/Element/AbstractElement.php index e1b705e0a5..5ff85b8fb1 100644 --- a/src/PhpWord/Element/AbstractElement.php +++ b/src/PhpWord/Element/AbstractElement.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/Bookmark.php b/src/PhpWord/Element/Bookmark.php index 8d4e0af53e..16b020d741 100644 --- a/src/PhpWord/Element/Bookmark.php +++ b/src/PhpWord/Element/Bookmark.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/Cell.php b/src/PhpWord/Element/Cell.php index b5250cd6c3..68f5df6255 100644 --- a/src/PhpWord/Element/Cell.php +++ b/src/PhpWord/Element/Cell.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/Chart.php b/src/PhpWord/Element/Chart.php index c340da4058..755f45e160 100644 --- a/src/PhpWord/Element/Chart.php +++ b/src/PhpWord/Element/Chart.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/CheckBox.php b/src/PhpWord/Element/CheckBox.php index e0a94fdfcd..f3e87176ef 100644 --- a/src/PhpWord/Element/CheckBox.php +++ b/src/PhpWord/Element/CheckBox.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/Comment.php b/src/PhpWord/Element/Comment.php index 205ff598b9..96ad15ef4e 100644 --- a/src/PhpWord/Element/Comment.php +++ b/src/PhpWord/Element/Comment.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/Endnote.php b/src/PhpWord/Element/Endnote.php index b6e94fba14..b962719502 100644 --- a/src/PhpWord/Element/Endnote.php +++ b/src/PhpWord/Element/Endnote.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/Field.php b/src/PhpWord/Element/Field.php index de50496520..5171e9a6bb 100644 --- a/src/PhpWord/Element/Field.php +++ b/src/PhpWord/Element/Field.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/Footer.php b/src/PhpWord/Element/Footer.php index 08ff525a1f..0290d7c1de 100644 --- a/src/PhpWord/Element/Footer.php +++ b/src/PhpWord/Element/Footer.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/Footnote.php b/src/PhpWord/Element/Footnote.php index e9a1bfc266..90aabccca9 100644 --- a/src/PhpWord/Element/Footnote.php +++ b/src/PhpWord/Element/Footnote.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/FormField.php b/src/PhpWord/Element/FormField.php index 598d61dc2f..f937df59c4 100644 --- a/src/PhpWord/Element/FormField.php +++ b/src/PhpWord/Element/FormField.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/Header.php b/src/PhpWord/Element/Header.php index ee8208773a..8a01946ea9 100644 --- a/src/PhpWord/Element/Header.php +++ b/src/PhpWord/Element/Header.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/Image.php b/src/PhpWord/Element/Image.php index 5e73d4e495..0363706782 100644 --- a/src/PhpWord/Element/Image.php +++ b/src/PhpWord/Element/Image.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/Line.php b/src/PhpWord/Element/Line.php index eba664730f..7e40b9402d 100644 --- a/src/PhpWord/Element/Line.php +++ b/src/PhpWord/Element/Line.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/Link.php b/src/PhpWord/Element/Link.php index 4637120ab5..2bec32ddc4 100644 --- a/src/PhpWord/Element/Link.php +++ b/src/PhpWord/Element/Link.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/ListItem.php b/src/PhpWord/Element/ListItem.php index cb55c5ae86..8b064c47b5 100644 --- a/src/PhpWord/Element/ListItem.php +++ b/src/PhpWord/Element/ListItem.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/ListItemRun.php b/src/PhpWord/Element/ListItemRun.php index e311dc2470..6e48a69012 100644 --- a/src/PhpWord/Element/ListItemRun.php +++ b/src/PhpWord/Element/ListItemRun.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord -* @copyright 2010-2017 PHPWord contributors +* @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/OLEObject.php b/src/PhpWord/Element/OLEObject.php index 5da94c3a82..c0c7f21798 100644 --- a/src/PhpWord/Element/OLEObject.php +++ b/src/PhpWord/Element/OLEObject.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/PageBreak.php b/src/PhpWord/Element/PageBreak.php index e41e807bef..1e2ada80ad 100644 --- a/src/PhpWord/Element/PageBreak.php +++ b/src/PhpWord/Element/PageBreak.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/PreserveText.php b/src/PhpWord/Element/PreserveText.php index ad20d7a30e..1ce2dcdd78 100644 --- a/src/PhpWord/Element/PreserveText.php +++ b/src/PhpWord/Element/PreserveText.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/Row.php b/src/PhpWord/Element/Row.php index 2e89b35495..da4dfe5d73 100644 --- a/src/PhpWord/Element/Row.php +++ b/src/PhpWord/Element/Row.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/SDT.php b/src/PhpWord/Element/SDT.php index 86f445cc46..a866d1bdac 100644 --- a/src/PhpWord/Element/SDT.php +++ b/src/PhpWord/Element/SDT.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/Section.php b/src/PhpWord/Element/Section.php index 06acf1f9b2..d612fc0172 100644 --- a/src/PhpWord/Element/Section.php +++ b/src/PhpWord/Element/Section.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/Shape.php b/src/PhpWord/Element/Shape.php index b553a4ac5e..d143c9b694 100644 --- a/src/PhpWord/Element/Shape.php +++ b/src/PhpWord/Element/Shape.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/TOC.php b/src/PhpWord/Element/TOC.php index e3ca0a08c2..c51d0e6be3 100644 --- a/src/PhpWord/Element/TOC.php +++ b/src/PhpWord/Element/TOC.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/Table.php b/src/PhpWord/Element/Table.php index 3a045031aa..10c4db69ab 100644 --- a/src/PhpWord/Element/Table.php +++ b/src/PhpWord/Element/Table.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/Text.php b/src/PhpWord/Element/Text.php index 4de12176ca..f4d7f08185 100644 --- a/src/PhpWord/Element/Text.php +++ b/src/PhpWord/Element/Text.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/TextBox.php b/src/PhpWord/Element/TextBox.php index 8058d0c983..b9f274d6b8 100644 --- a/src/PhpWord/Element/TextBox.php +++ b/src/PhpWord/Element/TextBox.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/TextBreak.php b/src/PhpWord/Element/TextBreak.php index 4cf65f35c1..385fec5a84 100644 --- a/src/PhpWord/Element/TextBreak.php +++ b/src/PhpWord/Element/TextBreak.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/TextRun.php b/src/PhpWord/Element/TextRun.php index 6d9ae9f4a1..9af55d4687 100644 --- a/src/PhpWord/Element/TextRun.php +++ b/src/PhpWord/Element/TextRun.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/Title.php b/src/PhpWord/Element/Title.php index ed06fa1342..569cea925c 100644 --- a/src/PhpWord/Element/Title.php +++ b/src/PhpWord/Element/Title.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Element/TrackChange.php b/src/PhpWord/Element/TrackChange.php index dde616cc21..410ffb7c9e 100644 --- a/src/PhpWord/Element/TrackChange.php +++ b/src/PhpWord/Element/TrackChange.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Escaper/AbstractEscaper.php b/src/PhpWord/Escaper/AbstractEscaper.php index 8207e2c67f..1575c069e2 100644 --- a/src/PhpWord/Escaper/AbstractEscaper.php +++ b/src/PhpWord/Escaper/AbstractEscaper.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Escaper/EscaperInterface.php b/src/PhpWord/Escaper/EscaperInterface.php index 1ef35c1b06..deb2cfbc0e 100644 --- a/src/PhpWord/Escaper/EscaperInterface.php +++ b/src/PhpWord/Escaper/EscaperInterface.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Escaper/RegExp.php b/src/PhpWord/Escaper/RegExp.php index 2f4e12ecde..f69aad8217 100644 --- a/src/PhpWord/Escaper/RegExp.php +++ b/src/PhpWord/Escaper/RegExp.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Escaper/Rtf.php b/src/PhpWord/Escaper/Rtf.php index 35f91ada5b..b8e0b2169c 100644 --- a/src/PhpWord/Escaper/Rtf.php +++ b/src/PhpWord/Escaper/Rtf.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Escaper/Xml.php b/src/PhpWord/Escaper/Xml.php index 81cedaa956..a769c5e189 100644 --- a/src/PhpWord/Escaper/Xml.php +++ b/src/PhpWord/Escaper/Xml.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Exception/CopyFileException.php b/src/PhpWord/Exception/CopyFileException.php index a5c1da6a84..d1c3bd0123 100644 --- a/src/PhpWord/Exception/CopyFileException.php +++ b/src/PhpWord/Exception/CopyFileException.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Exception/CreateTemporaryFileException.php b/src/PhpWord/Exception/CreateTemporaryFileException.php index fafc8dac5a..c8a06429d8 100644 --- a/src/PhpWord/Exception/CreateTemporaryFileException.php +++ b/src/PhpWord/Exception/CreateTemporaryFileException.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Exception/Exception.php b/src/PhpWord/Exception/Exception.php index b94ed1befb..d874625cdc 100644 --- a/src/PhpWord/Exception/Exception.php +++ b/src/PhpWord/Exception/Exception.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Exception/InvalidImageException.php b/src/PhpWord/Exception/InvalidImageException.php index 0a7b8fedd4..07c966815a 100644 --- a/src/PhpWord/Exception/InvalidImageException.php +++ b/src/PhpWord/Exception/InvalidImageException.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Exception/InvalidObjectException.php b/src/PhpWord/Exception/InvalidObjectException.php index 540155065d..d8fef9613e 100644 --- a/src/PhpWord/Exception/InvalidObjectException.php +++ b/src/PhpWord/Exception/InvalidObjectException.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Exception/InvalidStyleException.php b/src/PhpWord/Exception/InvalidStyleException.php index e697f6cff6..58c1961ddd 100644 --- a/src/PhpWord/Exception/InvalidStyleException.php +++ b/src/PhpWord/Exception/InvalidStyleException.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Exception/UnsupportedImageTypeException.php b/src/PhpWord/Exception/UnsupportedImageTypeException.php index 73b41d049c..ee27065345 100644 --- a/src/PhpWord/Exception/UnsupportedImageTypeException.php +++ b/src/PhpWord/Exception/UnsupportedImageTypeException.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/IOFactory.php b/src/PhpWord/IOFactory.php index eed1f1630f..3929f485e4 100644 --- a/src/PhpWord/IOFactory.php +++ b/src/PhpWord/IOFactory.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Media.php b/src/PhpWord/Media.php index d987901054..cc1b290312 100644 --- a/src/PhpWord/Media.php +++ b/src/PhpWord/Media.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Metadata/Compatibility.php b/src/PhpWord/Metadata/Compatibility.php index 69f6f98a70..bf0363aa1a 100644 --- a/src/PhpWord/Metadata/Compatibility.php +++ b/src/PhpWord/Metadata/Compatibility.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Metadata/DocInfo.php b/src/PhpWord/Metadata/DocInfo.php index 09714f9e0c..27ef89aecb 100644 --- a/src/PhpWord/Metadata/DocInfo.php +++ b/src/PhpWord/Metadata/DocInfo.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Metadata/Protection.php b/src/PhpWord/Metadata/Protection.php index 39ebc3dead..584ed83e43 100644 --- a/src/PhpWord/Metadata/Protection.php +++ b/src/PhpWord/Metadata/Protection.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Metadata/Settings.php b/src/PhpWord/Metadata/Settings.php index 8ab5860948..b1552e0210 100644 --- a/src/PhpWord/Metadata/Settings.php +++ b/src/PhpWord/Metadata/Settings.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/PhpWord.php b/src/PhpWord/PhpWord.php index ff23f6ef25..6b6fd9ffe8 100644 --- a/src/PhpWord/PhpWord.php +++ b/src/PhpWord/PhpWord.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Reader/AbstractReader.php b/src/PhpWord/Reader/AbstractReader.php index f59a955683..7db285f758 100644 --- a/src/PhpWord/Reader/AbstractReader.php +++ b/src/PhpWord/Reader/AbstractReader.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Reader/HTML.php b/src/PhpWord/Reader/HTML.php index 4e8b5e8227..db9f20891c 100644 --- a/src/PhpWord/Reader/HTML.php +++ b/src/PhpWord/Reader/HTML.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Reader/MsDoc.php b/src/PhpWord/Reader/MsDoc.php index c134377ad7..d494522955 100644 --- a/src/PhpWord/Reader/MsDoc.php +++ b/src/PhpWord/Reader/MsDoc.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Reader/ODText.php b/src/PhpWord/Reader/ODText.php index 5a22b4bac0..0b58dc50e1 100644 --- a/src/PhpWord/Reader/ODText.php +++ b/src/PhpWord/Reader/ODText.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Reader/ODText/AbstractPart.php b/src/PhpWord/Reader/ODText/AbstractPart.php index bdac3b6fdb..ff664e01fa 100644 --- a/src/PhpWord/Reader/ODText/AbstractPart.php +++ b/src/PhpWord/Reader/ODText/AbstractPart.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Reader/ODText/Content.php b/src/PhpWord/Reader/ODText/Content.php index 7a7a046837..9dfd645320 100644 --- a/src/PhpWord/Reader/ODText/Content.php +++ b/src/PhpWord/Reader/ODText/Content.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Reader/ODText/Meta.php b/src/PhpWord/Reader/ODText/Meta.php index 98832d175c..8801a5439a 100644 --- a/src/PhpWord/Reader/ODText/Meta.php +++ b/src/PhpWord/Reader/ODText/Meta.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Reader/RTF.php b/src/PhpWord/Reader/RTF.php index 2d09a04d2c..620252ffd7 100644 --- a/src/PhpWord/Reader/RTF.php +++ b/src/PhpWord/Reader/RTF.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Reader/RTF/Document.php b/src/PhpWord/Reader/RTF/Document.php index be16d707ba..b9509d71fe 100644 --- a/src/PhpWord/Reader/RTF/Document.php +++ b/src/PhpWord/Reader/RTF/Document.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Reader/ReaderInterface.php b/src/PhpWord/Reader/ReaderInterface.php index 3b2e357b71..4024cdb3d6 100644 --- a/src/PhpWord/Reader/ReaderInterface.php +++ b/src/PhpWord/Reader/ReaderInterface.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Reader/Word2007.php b/src/PhpWord/Reader/Word2007.php index 6c2178ad9a..deed3ce39c 100644 --- a/src/PhpWord/Reader/Word2007.php +++ b/src/PhpWord/Reader/Word2007.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 7ba53ad18d..342d9d111d 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Reader/Word2007/DocPropsApp.php b/src/PhpWord/Reader/Word2007/DocPropsApp.php index df34c9c37b..decc510390 100644 --- a/src/PhpWord/Reader/Word2007/DocPropsApp.php +++ b/src/PhpWord/Reader/Word2007/DocPropsApp.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Reader/Word2007/DocPropsCore.php b/src/PhpWord/Reader/Word2007/DocPropsCore.php index f82c6b4bf5..36eecebeae 100644 --- a/src/PhpWord/Reader/Word2007/DocPropsCore.php +++ b/src/PhpWord/Reader/Word2007/DocPropsCore.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Reader/Word2007/DocPropsCustom.php b/src/PhpWord/Reader/Word2007/DocPropsCustom.php index a3d6b90bd2..a6835aacc1 100644 --- a/src/PhpWord/Reader/Word2007/DocPropsCustom.php +++ b/src/PhpWord/Reader/Word2007/DocPropsCustom.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Reader/Word2007/Document.php b/src/PhpWord/Reader/Word2007/Document.php index ff094bcc29..4e37541b70 100644 --- a/src/PhpWord/Reader/Word2007/Document.php +++ b/src/PhpWord/Reader/Word2007/Document.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Reader/Word2007/Endnotes.php b/src/PhpWord/Reader/Word2007/Endnotes.php index 0f46cb2f47..aa8b65d750 100644 --- a/src/PhpWord/Reader/Word2007/Endnotes.php +++ b/src/PhpWord/Reader/Word2007/Endnotes.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Reader/Word2007/Footnotes.php b/src/PhpWord/Reader/Word2007/Footnotes.php index b69b26061c..634f473910 100644 --- a/src/PhpWord/Reader/Word2007/Footnotes.php +++ b/src/PhpWord/Reader/Word2007/Footnotes.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Reader/Word2007/Numbering.php b/src/PhpWord/Reader/Word2007/Numbering.php index c2a81dd5ac..3f57cbf8be 100644 --- a/src/PhpWord/Reader/Word2007/Numbering.php +++ b/src/PhpWord/Reader/Word2007/Numbering.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Reader/Word2007/Settings.php b/src/PhpWord/Reader/Word2007/Settings.php index ee057fe674..5cfe5453c9 100644 --- a/src/PhpWord/Reader/Word2007/Settings.php +++ b/src/PhpWord/Reader/Word2007/Settings.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Reader/Word2007/Styles.php b/src/PhpWord/Reader/Word2007/Styles.php index 8719641ec2..f343ad9296 100644 --- a/src/PhpWord/Reader/Word2007/Styles.php +++ b/src/PhpWord/Reader/Word2007/Styles.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Settings.php b/src/PhpWord/Settings.php index 22b8ba1f5e..8de1a8df80 100644 --- a/src/PhpWord/Settings.php +++ b/src/PhpWord/Settings.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Shared/AbstractEnum.php b/src/PhpWord/Shared/AbstractEnum.php index 442d8251b3..f2375d876e 100644 --- a/src/PhpWord/Shared/AbstractEnum.php +++ b/src/PhpWord/Shared/AbstractEnum.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Shared/Converter.php b/src/PhpWord/Shared/Converter.php index 56687c986a..c53f0030ce 100644 --- a/src/PhpWord/Shared/Converter.php +++ b/src/PhpWord/Shared/Converter.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 2c7cf1b5da..15f3b605c1 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Shared/Microsoft/PasswordEncoder.php b/src/PhpWord/Shared/Microsoft/PasswordEncoder.php index 1c7b4c6c8e..fc0c7ecdf8 100644 --- a/src/PhpWord/Shared/Microsoft/PasswordEncoder.php +++ b/src/PhpWord/Shared/Microsoft/PasswordEncoder.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Shared/OLERead.php b/src/PhpWord/Shared/OLERead.php index bcdda0c379..2e6a899e57 100644 --- a/src/PhpWord/Shared/OLERead.php +++ b/src/PhpWord/Shared/OLERead.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ namespace PhpOffice\PhpWord\Shared; diff --git a/src/PhpWord/Shared/ZipArchive.php b/src/PhpWord/Shared/ZipArchive.php index 3d8d0a4133..2783e17e1c 100644 --- a/src/PhpWord/Shared/ZipArchive.php +++ b/src/PhpWord/Shared/ZipArchive.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/SimpleType/DocProtect.php b/src/PhpWord/SimpleType/DocProtect.php index cffa0003ed..e386913d53 100644 --- a/src/PhpWord/SimpleType/DocProtect.php +++ b/src/PhpWord/SimpleType/DocProtect.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/SimpleType/Jc.php b/src/PhpWord/SimpleType/Jc.php index 5d0ee33b83..e55f824d14 100644 --- a/src/PhpWord/SimpleType/Jc.php +++ b/src/PhpWord/SimpleType/Jc.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/SimpleType/JcTable.php b/src/PhpWord/SimpleType/JcTable.php index 71e073977c..924a4f2014 100644 --- a/src/PhpWord/SimpleType/JcTable.php +++ b/src/PhpWord/SimpleType/JcTable.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/SimpleType/LineSpacingRule.php b/src/PhpWord/SimpleType/LineSpacingRule.php index f2cc5e638b..8fd8340c43 100644 --- a/src/PhpWord/SimpleType/LineSpacingRule.php +++ b/src/PhpWord/SimpleType/LineSpacingRule.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/SimpleType/NumberFormat.php b/src/PhpWord/SimpleType/NumberFormat.php index 480d85399a..83da66fa3f 100644 --- a/src/PhpWord/SimpleType/NumberFormat.php +++ b/src/PhpWord/SimpleType/NumberFormat.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/SimpleType/TblWidth.php b/src/PhpWord/SimpleType/TblWidth.php index 3d947bce7c..7fd753deb0 100644 --- a/src/PhpWord/SimpleType/TblWidth.php +++ b/src/PhpWord/SimpleType/TblWidth.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/SimpleType/TextAlignment.php b/src/PhpWord/SimpleType/TextAlignment.php index de36b10852..838b0c5e0e 100644 --- a/src/PhpWord/SimpleType/TextAlignment.php +++ b/src/PhpWord/SimpleType/TextAlignment.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/SimpleType/Zoom.php b/src/PhpWord/SimpleType/Zoom.php index 111e4ea16d..02c38fdb6a 100644 --- a/src/PhpWord/SimpleType/Zoom.php +++ b/src/PhpWord/SimpleType/Zoom.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style.php b/src/PhpWord/Style.php index 017b329003..47242621df 100644 --- a/src/PhpWord/Style.php +++ b/src/PhpWord/Style.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/AbstractStyle.php b/src/PhpWord/Style/AbstractStyle.php index 76ebd591c5..8edbe80bff 100644 --- a/src/PhpWord/Style/AbstractStyle.php +++ b/src/PhpWord/Style/AbstractStyle.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/Border.php b/src/PhpWord/Style/Border.php index ab6aef18b9..d032d07faa 100644 --- a/src/PhpWord/Style/Border.php +++ b/src/PhpWord/Style/Border.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/Cell.php b/src/PhpWord/Style/Cell.php index 8675ed7b11..e609e190ff 100644 --- a/src/PhpWord/Style/Cell.php +++ b/src/PhpWord/Style/Cell.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/Chart.php b/src/PhpWord/Style/Chart.php index 694fcddccc..58271fef1b 100644 --- a/src/PhpWord/Style/Chart.php +++ b/src/PhpWord/Style/Chart.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/Extrusion.php b/src/PhpWord/Style/Extrusion.php index 11c03edada..4c860bcd63 100644 --- a/src/PhpWord/Style/Extrusion.php +++ b/src/PhpWord/Style/Extrusion.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/Fill.php b/src/PhpWord/Style/Fill.php index 9b4730093b..360bcf3f0c 100644 --- a/src/PhpWord/Style/Fill.php +++ b/src/PhpWord/Style/Fill.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/Font.php b/src/PhpWord/Style/Font.php index 3095b79928..c58cee49ed 100644 --- a/src/PhpWord/Style/Font.php +++ b/src/PhpWord/Style/Font.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/Frame.php b/src/PhpWord/Style/Frame.php index bb684409b9..b926304902 100644 --- a/src/PhpWord/Style/Frame.php +++ b/src/PhpWord/Style/Frame.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/Image.php b/src/PhpWord/Style/Image.php index e0b972158d..70aafe12cd 100644 --- a/src/PhpWord/Style/Image.php +++ b/src/PhpWord/Style/Image.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/Indentation.php b/src/PhpWord/Style/Indentation.php index 9621714c74..e422395c80 100644 --- a/src/PhpWord/Style/Indentation.php +++ b/src/PhpWord/Style/Indentation.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/Language.php b/src/PhpWord/Style/Language.php index e09421e05e..91f948f5cb 100644 --- a/src/PhpWord/Style/Language.php +++ b/src/PhpWord/Style/Language.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/Line.php b/src/PhpWord/Style/Line.php index 16d15950a2..a9952eec0b 100644 --- a/src/PhpWord/Style/Line.php +++ b/src/PhpWord/Style/Line.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/LineNumbering.php b/src/PhpWord/Style/LineNumbering.php index b5f3c263e7..451252d87a 100644 --- a/src/PhpWord/Style/LineNumbering.php +++ b/src/PhpWord/Style/LineNumbering.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/ListItem.php b/src/PhpWord/Style/ListItem.php index 444341dc19..306ecff305 100644 --- a/src/PhpWord/Style/ListItem.php +++ b/src/PhpWord/Style/ListItem.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/Numbering.php b/src/PhpWord/Style/Numbering.php index 80ed5dca66..f7855cfa20 100644 --- a/src/PhpWord/Style/Numbering.php +++ b/src/PhpWord/Style/Numbering.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/NumberingLevel.php b/src/PhpWord/Style/NumberingLevel.php index 33c151e490..e9b32f0135 100644 --- a/src/PhpWord/Style/NumberingLevel.php +++ b/src/PhpWord/Style/NumberingLevel.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/Outline.php b/src/PhpWord/Style/Outline.php index fb7e028a8b..a04ad974c0 100644 --- a/src/PhpWord/Style/Outline.php +++ b/src/PhpWord/Style/Outline.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/Paper.php b/src/PhpWord/Style/Paper.php index 09e4769e90..3c93ed8f2f 100644 --- a/src/PhpWord/Style/Paper.php +++ b/src/PhpWord/Style/Paper.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/Paragraph.php b/src/PhpWord/Style/Paragraph.php index 53a9b958fc..ac58768695 100644 --- a/src/PhpWord/Style/Paragraph.php +++ b/src/PhpWord/Style/Paragraph.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/Row.php b/src/PhpWord/Style/Row.php index b56c6f5fa9..ad801af6e2 100644 --- a/src/PhpWord/Style/Row.php +++ b/src/PhpWord/Style/Row.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/Section.php b/src/PhpWord/Style/Section.php index 476846f5f2..162e08e0bc 100644 --- a/src/PhpWord/Style/Section.php +++ b/src/PhpWord/Style/Section.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/Shading.php b/src/PhpWord/Style/Shading.php index eeb055b2c8..154df26c7a 100644 --- a/src/PhpWord/Style/Shading.php +++ b/src/PhpWord/Style/Shading.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/Shadow.php b/src/PhpWord/Style/Shadow.php index 71d1e3e009..1379a32096 100644 --- a/src/PhpWord/Style/Shadow.php +++ b/src/PhpWord/Style/Shadow.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/Shape.php b/src/PhpWord/Style/Shape.php index fc84241d75..0c3f817982 100644 --- a/src/PhpWord/Style/Shape.php +++ b/src/PhpWord/Style/Shape.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/Spacing.php b/src/PhpWord/Style/Spacing.php index 489eb5d707..9bfb22822b 100644 --- a/src/PhpWord/Style/Spacing.php +++ b/src/PhpWord/Style/Spacing.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/TOC.php b/src/PhpWord/Style/TOC.php index 938e6de166..2efd54a4a4 100644 --- a/src/PhpWord/Style/TOC.php +++ b/src/PhpWord/Style/TOC.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/Tab.php b/src/PhpWord/Style/Tab.php index 09e49e02c0..d3cf5bd7f4 100644 --- a/src/PhpWord/Style/Tab.php +++ b/src/PhpWord/Style/Tab.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/Table.php b/src/PhpWord/Style/Table.php index 92a24ddec9..feb028da2c 100644 --- a/src/PhpWord/Style/Table.php +++ b/src/PhpWord/Style/Table.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/TablePosition.php b/src/PhpWord/Style/TablePosition.php index 7cb0a0be16..d4b7083102 100644 --- a/src/PhpWord/Style/TablePosition.php +++ b/src/PhpWord/Style/TablePosition.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Style/TextBox.php b/src/PhpWord/Style/TextBox.php index 91adc0afd2..e9c0f0c064 100644 --- a/src/PhpWord/Style/TextBox.php +++ b/src/PhpWord/Style/TextBox.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Template.php b/src/PhpWord/Template.php index a4769927a0..c42696f08c 100644 --- a/src/PhpWord/Template.php +++ b/src/PhpWord/Template.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index 269b25e95e..72446ae744 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/AbstractWriter.php b/src/PhpWord/Writer/AbstractWriter.php index bb943d7ea5..7e0d511a55 100644 --- a/src/PhpWord/Writer/AbstractWriter.php +++ b/src/PhpWord/Writer/AbstractWriter.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/HTML.php b/src/PhpWord/Writer/HTML.php index 9b098dd8cd..7f55b9d3e6 100644 --- a/src/PhpWord/Writer/HTML.php +++ b/src/PhpWord/Writer/HTML.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/HTML/Element/AbstractElement.php b/src/PhpWord/Writer/HTML/Element/AbstractElement.php index 47f0f93cb9..dc5ccfaadc 100644 --- a/src/PhpWord/Writer/HTML/Element/AbstractElement.php +++ b/src/PhpWord/Writer/HTML/Element/AbstractElement.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/HTML/Element/Bookmark.php b/src/PhpWord/Writer/HTML/Element/Bookmark.php index 649cc7b86c..082bd76073 100644 --- a/src/PhpWord/Writer/HTML/Element/Bookmark.php +++ b/src/PhpWord/Writer/HTML/Element/Bookmark.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/HTML/Element/Container.php b/src/PhpWord/Writer/HTML/Element/Container.php index 677b6173b4..006b588918 100644 --- a/src/PhpWord/Writer/HTML/Element/Container.php +++ b/src/PhpWord/Writer/HTML/Element/Container.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/HTML/Element/Endnote.php b/src/PhpWord/Writer/HTML/Element/Endnote.php index c4a3e4365a..2252dc3af8 100644 --- a/src/PhpWord/Writer/HTML/Element/Endnote.php +++ b/src/PhpWord/Writer/HTML/Element/Endnote.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/HTML/Element/Footnote.php b/src/PhpWord/Writer/HTML/Element/Footnote.php index 60b246f878..ed14db1e04 100644 --- a/src/PhpWord/Writer/HTML/Element/Footnote.php +++ b/src/PhpWord/Writer/HTML/Element/Footnote.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/HTML/Element/Image.php b/src/PhpWord/Writer/HTML/Element/Image.php index 3e516b53a1..7c22a1663d 100644 --- a/src/PhpWord/Writer/HTML/Element/Image.php +++ b/src/PhpWord/Writer/HTML/Element/Image.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/HTML/Element/Link.php b/src/PhpWord/Writer/HTML/Element/Link.php index f29880d4c9..f6dae5cdd3 100644 --- a/src/PhpWord/Writer/HTML/Element/Link.php +++ b/src/PhpWord/Writer/HTML/Element/Link.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/HTML/Element/ListItem.php b/src/PhpWord/Writer/HTML/Element/ListItem.php index 02b25eb98a..384b3ef165 100644 --- a/src/PhpWord/Writer/HTML/Element/ListItem.php +++ b/src/PhpWord/Writer/HTML/Element/ListItem.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/HTML/Element/PageBreak.php b/src/PhpWord/Writer/HTML/Element/PageBreak.php index 5cab272479..f9998e3793 100644 --- a/src/PhpWord/Writer/HTML/Element/PageBreak.php +++ b/src/PhpWord/Writer/HTML/Element/PageBreak.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/HTML/Element/Table.php b/src/PhpWord/Writer/HTML/Element/Table.php index c7d8670b16..95f7c1fa91 100644 --- a/src/PhpWord/Writer/HTML/Element/Table.php +++ b/src/PhpWord/Writer/HTML/Element/Table.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/HTML/Element/Text.php b/src/PhpWord/Writer/HTML/Element/Text.php index 9f8f7773c5..04d76a8327 100644 --- a/src/PhpWord/Writer/HTML/Element/Text.php +++ b/src/PhpWord/Writer/HTML/Element/Text.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/HTML/Element/TextBreak.php b/src/PhpWord/Writer/HTML/Element/TextBreak.php index 93ab924a50..6ff092dbf7 100644 --- a/src/PhpWord/Writer/HTML/Element/TextBreak.php +++ b/src/PhpWord/Writer/HTML/Element/TextBreak.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/HTML/Element/TextRun.php b/src/PhpWord/Writer/HTML/Element/TextRun.php index d7461539d9..b2deaf25d8 100644 --- a/src/PhpWord/Writer/HTML/Element/TextRun.php +++ b/src/PhpWord/Writer/HTML/Element/TextRun.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/HTML/Element/Title.php b/src/PhpWord/Writer/HTML/Element/Title.php index ee8f271b19..3a80201848 100644 --- a/src/PhpWord/Writer/HTML/Element/Title.php +++ b/src/PhpWord/Writer/HTML/Element/Title.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/HTML/Part/AbstractPart.php b/src/PhpWord/Writer/HTML/Part/AbstractPart.php index 7b6e0c3ea3..2d86f399b0 100644 --- a/src/PhpWord/Writer/HTML/Part/AbstractPart.php +++ b/src/PhpWord/Writer/HTML/Part/AbstractPart.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/HTML/Part/Body.php b/src/PhpWord/Writer/HTML/Part/Body.php index eea173500d..a029f96534 100644 --- a/src/PhpWord/Writer/HTML/Part/Body.php +++ b/src/PhpWord/Writer/HTML/Part/Body.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/HTML/Part/Head.php b/src/PhpWord/Writer/HTML/Part/Head.php index f4d630145f..1107becf84 100644 --- a/src/PhpWord/Writer/HTML/Part/Head.php +++ b/src/PhpWord/Writer/HTML/Part/Head.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/HTML/Style/AbstractStyle.php b/src/PhpWord/Writer/HTML/Style/AbstractStyle.php index fa27c085ca..cfb54cb8d7 100644 --- a/src/PhpWord/Writer/HTML/Style/AbstractStyle.php +++ b/src/PhpWord/Writer/HTML/Style/AbstractStyle.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/HTML/Style/Font.php b/src/PhpWord/Writer/HTML/Style/Font.php index 8daa8823c8..1aeaa347f9 100644 --- a/src/PhpWord/Writer/HTML/Style/Font.php +++ b/src/PhpWord/Writer/HTML/Style/Font.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/HTML/Style/Generic.php b/src/PhpWord/Writer/HTML/Style/Generic.php index 73830707b1..ee5d089607 100644 --- a/src/PhpWord/Writer/HTML/Style/Generic.php +++ b/src/PhpWord/Writer/HTML/Style/Generic.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/HTML/Style/Image.php b/src/PhpWord/Writer/HTML/Style/Image.php index 178b14348e..93747b4645 100644 --- a/src/PhpWord/Writer/HTML/Style/Image.php +++ b/src/PhpWord/Writer/HTML/Style/Image.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/HTML/Style/Paragraph.php b/src/PhpWord/Writer/HTML/Style/Paragraph.php index 57e44e8594..863ef93b14 100644 --- a/src/PhpWord/Writer/HTML/Style/Paragraph.php +++ b/src/PhpWord/Writer/HTML/Style/Paragraph.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/ODText.php b/src/PhpWord/Writer/ODText.php index 7158874c11..efd0d6a923 100644 --- a/src/PhpWord/Writer/ODText.php +++ b/src/PhpWord/Writer/ODText.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/ODText/Element/AbstractElement.php b/src/PhpWord/Writer/ODText/Element/AbstractElement.php index 481995ff80..9c9fc1c477 100644 --- a/src/PhpWord/Writer/ODText/Element/AbstractElement.php +++ b/src/PhpWord/Writer/ODText/Element/AbstractElement.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/ODText/Element/Container.php b/src/PhpWord/Writer/ODText/Element/Container.php index 112e71e87f..6ba8124f0f 100644 --- a/src/PhpWord/Writer/ODText/Element/Container.php +++ b/src/PhpWord/Writer/ODText/Element/Container.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/ODText/Element/Image.php b/src/PhpWord/Writer/ODText/Element/Image.php index 2c0b4727d2..add45e1044 100644 --- a/src/PhpWord/Writer/ODText/Element/Image.php +++ b/src/PhpWord/Writer/ODText/Element/Image.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/ODText/Element/Link.php b/src/PhpWord/Writer/ODText/Element/Link.php index 34d72c1ac7..d6fec50777 100644 --- a/src/PhpWord/Writer/ODText/Element/Link.php +++ b/src/PhpWord/Writer/ODText/Element/Link.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/ODText/Element/PageBreak.php b/src/PhpWord/Writer/ODText/Element/PageBreak.php index 6eee6cfc94..ecf4760740 100644 --- a/src/PhpWord/Writer/ODText/Element/PageBreak.php +++ b/src/PhpWord/Writer/ODText/Element/PageBreak.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/ODText/Element/Table.php b/src/PhpWord/Writer/ODText/Element/Table.php index cdc2a0e3cd..8a21ee1b47 100644 --- a/src/PhpWord/Writer/ODText/Element/Table.php +++ b/src/PhpWord/Writer/ODText/Element/Table.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/ODText/Element/Text.php b/src/PhpWord/Writer/ODText/Element/Text.php index f9259fc501..7dcd28a013 100644 --- a/src/PhpWord/Writer/ODText/Element/Text.php +++ b/src/PhpWord/Writer/ODText/Element/Text.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/ODText/Element/TextBreak.php b/src/PhpWord/Writer/ODText/Element/TextBreak.php index f7642e3b28..80cd13870a 100644 --- a/src/PhpWord/Writer/ODText/Element/TextBreak.php +++ b/src/PhpWord/Writer/ODText/Element/TextBreak.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/ODText/Element/TextRun.php b/src/PhpWord/Writer/ODText/Element/TextRun.php index f5c855fe33..78e5a8adae 100644 --- a/src/PhpWord/Writer/ODText/Element/TextRun.php +++ b/src/PhpWord/Writer/ODText/Element/TextRun.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/ODText/Element/Title.php b/src/PhpWord/Writer/ODText/Element/Title.php index 769d293f5d..343949a2f1 100644 --- a/src/PhpWord/Writer/ODText/Element/Title.php +++ b/src/PhpWord/Writer/ODText/Element/Title.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/ODText/Part/AbstractPart.php b/src/PhpWord/Writer/ODText/Part/AbstractPart.php index 74412fd42b..f2844de6f0 100644 --- a/src/PhpWord/Writer/ODText/Part/AbstractPart.php +++ b/src/PhpWord/Writer/ODText/Part/AbstractPart.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/ODText/Part/Content.php b/src/PhpWord/Writer/ODText/Part/Content.php index f91ad5441e..a50eea7ba0 100644 --- a/src/PhpWord/Writer/ODText/Part/Content.php +++ b/src/PhpWord/Writer/ODText/Part/Content.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/ODText/Part/Manifest.php b/src/PhpWord/Writer/ODText/Part/Manifest.php index d916ccdfb4..f952b4c072 100644 --- a/src/PhpWord/Writer/ODText/Part/Manifest.php +++ b/src/PhpWord/Writer/ODText/Part/Manifest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/ODText/Part/Meta.php b/src/PhpWord/Writer/ODText/Part/Meta.php index f592c5f034..f38ad01d56 100644 --- a/src/PhpWord/Writer/ODText/Part/Meta.php +++ b/src/PhpWord/Writer/ODText/Part/Meta.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/ODText/Part/Mimetype.php b/src/PhpWord/Writer/ODText/Part/Mimetype.php index 6e45b8485f..552f54403a 100644 --- a/src/PhpWord/Writer/ODText/Part/Mimetype.php +++ b/src/PhpWord/Writer/ODText/Part/Mimetype.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/ODText/Part/Styles.php b/src/PhpWord/Writer/ODText/Part/Styles.php index e49fa25e34..e7635e9854 100644 --- a/src/PhpWord/Writer/ODText/Part/Styles.php +++ b/src/PhpWord/Writer/ODText/Part/Styles.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/ODText/Style/AbstractStyle.php b/src/PhpWord/Writer/ODText/Style/AbstractStyle.php index 26b9905bd5..f7679ab22c 100644 --- a/src/PhpWord/Writer/ODText/Style/AbstractStyle.php +++ b/src/PhpWord/Writer/ODText/Style/AbstractStyle.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/ODText/Style/Font.php b/src/PhpWord/Writer/ODText/Style/Font.php index 50de32adad..7c7d20ddd2 100644 --- a/src/PhpWord/Writer/ODText/Style/Font.php +++ b/src/PhpWord/Writer/ODText/Style/Font.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/ODText/Style/Image.php b/src/PhpWord/Writer/ODText/Style/Image.php index b85d4d70a6..13005a7f03 100644 --- a/src/PhpWord/Writer/ODText/Style/Image.php +++ b/src/PhpWord/Writer/ODText/Style/Image.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/ODText/Style/Paragraph.php b/src/PhpWord/Writer/ODText/Style/Paragraph.php index 14a811a52d..223d02f047 100644 --- a/src/PhpWord/Writer/ODText/Style/Paragraph.php +++ b/src/PhpWord/Writer/ODText/Style/Paragraph.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/ODText/Style/Section.php b/src/PhpWord/Writer/ODText/Style/Section.php index bef023e9f3..92d8891170 100644 --- a/src/PhpWord/Writer/ODText/Style/Section.php +++ b/src/PhpWord/Writer/ODText/Style/Section.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/ODText/Style/Table.php b/src/PhpWord/Writer/ODText/Style/Table.php index 7d66899ac7..249321cff8 100644 --- a/src/PhpWord/Writer/ODText/Style/Table.php +++ b/src/PhpWord/Writer/ODText/Style/Table.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/PDF.php b/src/PhpWord/Writer/PDF.php index 45fe8f3518..64dcc7898d 100644 --- a/src/PhpWord/Writer/PDF.php +++ b/src/PhpWord/Writer/PDF.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PhpWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/PDF/AbstractRenderer.php b/src/PhpWord/Writer/PDF/AbstractRenderer.php index 7b668e0b89..5f9e3b3a8c 100644 --- a/src/PhpWord/Writer/PDF/AbstractRenderer.php +++ b/src/PhpWord/Writer/PDF/AbstractRenderer.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PhpWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/PDF/DomPDF.php b/src/PhpWord/Writer/PDF/DomPDF.php index be282d2026..5fa8f75dbb 100644 --- a/src/PhpWord/Writer/PDF/DomPDF.php +++ b/src/PhpWord/Writer/PDF/DomPDF.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PhpWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/PDF/MPDF.php b/src/PhpWord/Writer/PDF/MPDF.php index b6980a9d59..e63f5dfd68 100644 --- a/src/PhpWord/Writer/PDF/MPDF.php +++ b/src/PhpWord/Writer/PDF/MPDF.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PhpWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/PDF/TCPDF.php b/src/PhpWord/Writer/PDF/TCPDF.php index 85e3614c08..badab0460e 100644 --- a/src/PhpWord/Writer/PDF/TCPDF.php +++ b/src/PhpWord/Writer/PDF/TCPDF.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PhpWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/RTF.php b/src/PhpWord/Writer/RTF.php index 7756253ab7..0604e8b56b 100644 --- a/src/PhpWord/Writer/RTF.php +++ b/src/PhpWord/Writer/RTF.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/RTF/Element/AbstractElement.php b/src/PhpWord/Writer/RTF/Element/AbstractElement.php index 1013ee3685..cf1aa391c5 100644 --- a/src/PhpWord/Writer/RTF/Element/AbstractElement.php +++ b/src/PhpWord/Writer/RTF/Element/AbstractElement.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/RTF/Element/Container.php b/src/PhpWord/Writer/RTF/Element/Container.php index 4850c8bf2d..58c19256dc 100644 --- a/src/PhpWord/Writer/RTF/Element/Container.php +++ b/src/PhpWord/Writer/RTF/Element/Container.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/RTF/Element/Image.php b/src/PhpWord/Writer/RTF/Element/Image.php index fb96baffe5..f1e727007b 100644 --- a/src/PhpWord/Writer/RTF/Element/Image.php +++ b/src/PhpWord/Writer/RTF/Element/Image.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/RTF/Element/Link.php b/src/PhpWord/Writer/RTF/Element/Link.php index 91a75720dc..25954ed878 100644 --- a/src/PhpWord/Writer/RTF/Element/Link.php +++ b/src/PhpWord/Writer/RTF/Element/Link.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/RTF/Element/ListItem.php b/src/PhpWord/Writer/RTF/Element/ListItem.php index e628bffd36..29e7f6607d 100644 --- a/src/PhpWord/Writer/RTF/Element/ListItem.php +++ b/src/PhpWord/Writer/RTF/Element/ListItem.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/RTF/Element/PageBreak.php b/src/PhpWord/Writer/RTF/Element/PageBreak.php index 0adbe06e96..6b08c9cc44 100644 --- a/src/PhpWord/Writer/RTF/Element/PageBreak.php +++ b/src/PhpWord/Writer/RTF/Element/PageBreak.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/RTF/Element/Table.php b/src/PhpWord/Writer/RTF/Element/Table.php index d0bc08457e..8154aa7cf5 100644 --- a/src/PhpWord/Writer/RTF/Element/Table.php +++ b/src/PhpWord/Writer/RTF/Element/Table.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/RTF/Element/Text.php b/src/PhpWord/Writer/RTF/Element/Text.php index 2fac052088..f80e793534 100644 --- a/src/PhpWord/Writer/RTF/Element/Text.php +++ b/src/PhpWord/Writer/RTF/Element/Text.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/RTF/Element/TextBreak.php b/src/PhpWord/Writer/RTF/Element/TextBreak.php index 2009fcfff1..4aab27677a 100644 --- a/src/PhpWord/Writer/RTF/Element/TextBreak.php +++ b/src/PhpWord/Writer/RTF/Element/TextBreak.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/RTF/Element/TextRun.php b/src/PhpWord/Writer/RTF/Element/TextRun.php index d4e5676552..bfd161f08a 100644 --- a/src/PhpWord/Writer/RTF/Element/TextRun.php +++ b/src/PhpWord/Writer/RTF/Element/TextRun.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/RTF/Element/Title.php b/src/PhpWord/Writer/RTF/Element/Title.php index 18bad9fd6a..a9940ca99a 100644 --- a/src/PhpWord/Writer/RTF/Element/Title.php +++ b/src/PhpWord/Writer/RTF/Element/Title.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/RTF/Part/AbstractPart.php b/src/PhpWord/Writer/RTF/Part/AbstractPart.php index 7569a105aa..8171b0d228 100644 --- a/src/PhpWord/Writer/RTF/Part/AbstractPart.php +++ b/src/PhpWord/Writer/RTF/Part/AbstractPart.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/RTF/Part/Document.php b/src/PhpWord/Writer/RTF/Part/Document.php index 465872eade..d4bfadb4c5 100644 --- a/src/PhpWord/Writer/RTF/Part/Document.php +++ b/src/PhpWord/Writer/RTF/Part/Document.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/RTF/Part/Header.php b/src/PhpWord/Writer/RTF/Part/Header.php index 73f1351f8a..01439bc6ad 100644 --- a/src/PhpWord/Writer/RTF/Part/Header.php +++ b/src/PhpWord/Writer/RTF/Part/Header.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/RTF/Style/AbstractStyle.php b/src/PhpWord/Writer/RTF/Style/AbstractStyle.php index 8052361092..57aa6bb9f7 100644 --- a/src/PhpWord/Writer/RTF/Style/AbstractStyle.php +++ b/src/PhpWord/Writer/RTF/Style/AbstractStyle.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/RTF/Style/Border.php b/src/PhpWord/Writer/RTF/Style/Border.php index 0ba9f60254..08dcf01810 100644 --- a/src/PhpWord/Writer/RTF/Style/Border.php +++ b/src/PhpWord/Writer/RTF/Style/Border.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/RTF/Style/Font.php b/src/PhpWord/Writer/RTF/Style/Font.php index 3338368ad4..8c729425d1 100644 --- a/src/PhpWord/Writer/RTF/Style/Font.php +++ b/src/PhpWord/Writer/RTF/Style/Font.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/RTF/Style/Paragraph.php b/src/PhpWord/Writer/RTF/Style/Paragraph.php index 61b61fd73c..3b8690cd4a 100644 --- a/src/PhpWord/Writer/RTF/Style/Paragraph.php +++ b/src/PhpWord/Writer/RTF/Style/Paragraph.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/RTF/Style/Section.php b/src/PhpWord/Writer/RTF/Style/Section.php index 8f073716ba..5c34fa8683 100644 --- a/src/PhpWord/Writer/RTF/Style/Section.php +++ b/src/PhpWord/Writer/RTF/Style/Section.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007.php b/src/PhpWord/Writer/Word2007.php index fcef982fe2..eee215bef0 100644 --- a/src/PhpWord/Writer/Word2007.php +++ b/src/PhpWord/Writer/Word2007.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/AbstractElement.php b/src/PhpWord/Writer/Word2007/Element/AbstractElement.php index 8c9f0bb7a6..63f45a761f 100644 --- a/src/PhpWord/Writer/Word2007/Element/AbstractElement.php +++ b/src/PhpWord/Writer/Word2007/Element/AbstractElement.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/Bookmark.php b/src/PhpWord/Writer/Word2007/Element/Bookmark.php index 4b0b78a73a..04eaacf37c 100644 --- a/src/PhpWord/Writer/Word2007/Element/Bookmark.php +++ b/src/PhpWord/Writer/Word2007/Element/Bookmark.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/Chart.php b/src/PhpWord/Writer/Word2007/Element/Chart.php index 591799ab5b..f88ca2d252 100644 --- a/src/PhpWord/Writer/Word2007/Element/Chart.php +++ b/src/PhpWord/Writer/Word2007/Element/Chart.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/CheckBox.php b/src/PhpWord/Writer/Word2007/Element/CheckBox.php index ab888f6757..05692a074d 100644 --- a/src/PhpWord/Writer/Word2007/Element/CheckBox.php +++ b/src/PhpWord/Writer/Word2007/Element/CheckBox.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/Container.php b/src/PhpWord/Writer/Word2007/Element/Container.php index b6d1145cf9..892da051ad 100644 --- a/src/PhpWord/Writer/Word2007/Element/Container.php +++ b/src/PhpWord/Writer/Word2007/Element/Container.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/Endnote.php b/src/PhpWord/Writer/Word2007/Element/Endnote.php index ebfe35c18d..9a2eb3ffab 100644 --- a/src/PhpWord/Writer/Word2007/Element/Endnote.php +++ b/src/PhpWord/Writer/Word2007/Element/Endnote.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/Field.php b/src/PhpWord/Writer/Word2007/Element/Field.php index 336a432574..cf3fbd6606 100644 --- a/src/PhpWord/Writer/Word2007/Element/Field.php +++ b/src/PhpWord/Writer/Word2007/Element/Field.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/Footnote.php b/src/PhpWord/Writer/Word2007/Element/Footnote.php index 65ef40c7f4..56a5332f07 100644 --- a/src/PhpWord/Writer/Word2007/Element/Footnote.php +++ b/src/PhpWord/Writer/Word2007/Element/Footnote.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/FormField.php b/src/PhpWord/Writer/Word2007/Element/FormField.php index c77ca37898..b59cf58f89 100644 --- a/src/PhpWord/Writer/Word2007/Element/FormField.php +++ b/src/PhpWord/Writer/Word2007/Element/FormField.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/Image.php b/src/PhpWord/Writer/Word2007/Element/Image.php index 32a22a132f..3614ec184f 100644 --- a/src/PhpWord/Writer/Word2007/Element/Image.php +++ b/src/PhpWord/Writer/Word2007/Element/Image.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/Line.php b/src/PhpWord/Writer/Word2007/Element/Line.php index 9b1a160d4e..a114be6006 100644 --- a/src/PhpWord/Writer/Word2007/Element/Line.php +++ b/src/PhpWord/Writer/Word2007/Element/Line.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/Link.php b/src/PhpWord/Writer/Word2007/Element/Link.php index dc708a618d..f0adf851e3 100644 --- a/src/PhpWord/Writer/Word2007/Element/Link.php +++ b/src/PhpWord/Writer/Word2007/Element/Link.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/ListItem.php b/src/PhpWord/Writer/Word2007/Element/ListItem.php index c1aa0ce3e5..ef738e10d7 100644 --- a/src/PhpWord/Writer/Word2007/Element/ListItem.php +++ b/src/PhpWord/Writer/Word2007/Element/ListItem.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/ListItemRun.php b/src/PhpWord/Writer/Word2007/Element/ListItemRun.php index e6ed2b46d2..765d2ee0f9 100644 --- a/src/PhpWord/Writer/Word2007/Element/ListItemRun.php +++ b/src/PhpWord/Writer/Word2007/Element/ListItemRun.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/OLEObject.php b/src/PhpWord/Writer/Word2007/Element/OLEObject.php index 50891d97f4..c55ff6cd8c 100644 --- a/src/PhpWord/Writer/Word2007/Element/OLEObject.php +++ b/src/PhpWord/Writer/Word2007/Element/OLEObject.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/PageBreak.php b/src/PhpWord/Writer/Word2007/Element/PageBreak.php index 04ff29d487..0801e4d3c4 100644 --- a/src/PhpWord/Writer/Word2007/Element/PageBreak.php +++ b/src/PhpWord/Writer/Word2007/Element/PageBreak.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/ParagraphAlignment.php b/src/PhpWord/Writer/Word2007/Element/ParagraphAlignment.php index 0dafa4a057..5563f6075d 100644 --- a/src/PhpWord/Writer/Word2007/Element/ParagraphAlignment.php +++ b/src/PhpWord/Writer/Word2007/Element/ParagraphAlignment.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/PreserveText.php b/src/PhpWord/Writer/Word2007/Element/PreserveText.php index 138878663c..94ce6eded7 100644 --- a/src/PhpWord/Writer/Word2007/Element/PreserveText.php +++ b/src/PhpWord/Writer/Word2007/Element/PreserveText.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/SDT.php b/src/PhpWord/Writer/Word2007/Element/SDT.php index 6a2025649b..21020a0f9e 100644 --- a/src/PhpWord/Writer/Word2007/Element/SDT.php +++ b/src/PhpWord/Writer/Word2007/Element/SDT.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/Shape.php b/src/PhpWord/Writer/Word2007/Element/Shape.php index 9f11129320..250d5c1d0d 100644 --- a/src/PhpWord/Writer/Word2007/Element/Shape.php +++ b/src/PhpWord/Writer/Word2007/Element/Shape.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/TOC.php b/src/PhpWord/Writer/Word2007/Element/TOC.php index 36ed7f88bc..94437cbf0d 100644 --- a/src/PhpWord/Writer/Word2007/Element/TOC.php +++ b/src/PhpWord/Writer/Word2007/Element/TOC.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/Table.php b/src/PhpWord/Writer/Word2007/Element/Table.php index c0590772bf..25a48ab2cc 100644 --- a/src/PhpWord/Writer/Word2007/Element/Table.php +++ b/src/PhpWord/Writer/Word2007/Element/Table.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/TableAlignment.php b/src/PhpWord/Writer/Word2007/Element/TableAlignment.php index 44450fd63b..f44e9ebe42 100644 --- a/src/PhpWord/Writer/Word2007/Element/TableAlignment.php +++ b/src/PhpWord/Writer/Word2007/Element/TableAlignment.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/Text.php b/src/PhpWord/Writer/Word2007/Element/Text.php index 130b912bad..f421c1afe8 100644 --- a/src/PhpWord/Writer/Word2007/Element/Text.php +++ b/src/PhpWord/Writer/Word2007/Element/Text.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/TextBox.php b/src/PhpWord/Writer/Word2007/Element/TextBox.php index 3780c698f0..9dd4bc3e57 100644 --- a/src/PhpWord/Writer/Word2007/Element/TextBox.php +++ b/src/PhpWord/Writer/Word2007/Element/TextBox.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/TextBreak.php b/src/PhpWord/Writer/Word2007/Element/TextBreak.php index 161a528e01..7b3d999706 100644 --- a/src/PhpWord/Writer/Word2007/Element/TextBreak.php +++ b/src/PhpWord/Writer/Word2007/Element/TextBreak.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/TextRun.php b/src/PhpWord/Writer/Word2007/Element/TextRun.php index 9fd70b135f..e46ad3f527 100644 --- a/src/PhpWord/Writer/Word2007/Element/TextRun.php +++ b/src/PhpWord/Writer/Word2007/Element/TextRun.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Element/Title.php b/src/PhpWord/Writer/Word2007/Element/Title.php index 80c0904d6a..858ecfefa7 100644 --- a/src/PhpWord/Writer/Word2007/Element/Title.php +++ b/src/PhpWord/Writer/Word2007/Element/Title.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Part/AbstractPart.php b/src/PhpWord/Writer/Word2007/Part/AbstractPart.php index 038eb21dc8..ce4e41cbd4 100644 --- a/src/PhpWord/Writer/Word2007/Part/AbstractPart.php +++ b/src/PhpWord/Writer/Word2007/Part/AbstractPart.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Part/Chart.php b/src/PhpWord/Writer/Word2007/Part/Chart.php index c3703f9f6d..3db542c5cb 100644 --- a/src/PhpWord/Writer/Word2007/Part/Chart.php +++ b/src/PhpWord/Writer/Word2007/Part/Chart.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Part/Comments.php b/src/PhpWord/Writer/Word2007/Part/Comments.php index 2b8f9267a2..33c9f59e6a 100644 --- a/src/PhpWord/Writer/Word2007/Part/Comments.php +++ b/src/PhpWord/Writer/Word2007/Part/Comments.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Part/ContentTypes.php b/src/PhpWord/Writer/Word2007/Part/ContentTypes.php index 9be988d345..28a2d29449 100644 --- a/src/PhpWord/Writer/Word2007/Part/ContentTypes.php +++ b/src/PhpWord/Writer/Word2007/Part/ContentTypes.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Part/DocPropsApp.php b/src/PhpWord/Writer/Word2007/Part/DocPropsApp.php index dbd551873f..3452d86496 100644 --- a/src/PhpWord/Writer/Word2007/Part/DocPropsApp.php +++ b/src/PhpWord/Writer/Word2007/Part/DocPropsApp.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Part/DocPropsCore.php b/src/PhpWord/Writer/Word2007/Part/DocPropsCore.php index fdabee36d0..caefbd8625 100644 --- a/src/PhpWord/Writer/Word2007/Part/DocPropsCore.php +++ b/src/PhpWord/Writer/Word2007/Part/DocPropsCore.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Part/DocPropsCustom.php b/src/PhpWord/Writer/Word2007/Part/DocPropsCustom.php index 8ee2f0284e..478075d30e 100644 --- a/src/PhpWord/Writer/Word2007/Part/DocPropsCustom.php +++ b/src/PhpWord/Writer/Word2007/Part/DocPropsCustom.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Part/Document.php b/src/PhpWord/Writer/Word2007/Part/Document.php index 72e4fcd8d1..986b498570 100644 --- a/src/PhpWord/Writer/Word2007/Part/Document.php +++ b/src/PhpWord/Writer/Word2007/Part/Document.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Part/Endnotes.php b/src/PhpWord/Writer/Word2007/Part/Endnotes.php index 289119db74..ce3a46bfb7 100644 --- a/src/PhpWord/Writer/Word2007/Part/Endnotes.php +++ b/src/PhpWord/Writer/Word2007/Part/Endnotes.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Part/FontTable.php b/src/PhpWord/Writer/Word2007/Part/FontTable.php index 065a318ec0..1161a951e6 100644 --- a/src/PhpWord/Writer/Word2007/Part/FontTable.php +++ b/src/PhpWord/Writer/Word2007/Part/FontTable.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Part/Footer.php b/src/PhpWord/Writer/Word2007/Part/Footer.php index cfc9dd40fa..97b4779042 100644 --- a/src/PhpWord/Writer/Word2007/Part/Footer.php +++ b/src/PhpWord/Writer/Word2007/Part/Footer.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Part/Footnotes.php b/src/PhpWord/Writer/Word2007/Part/Footnotes.php index c9e3bcac20..59bf183096 100644 --- a/src/PhpWord/Writer/Word2007/Part/Footnotes.php +++ b/src/PhpWord/Writer/Word2007/Part/Footnotes.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Part/Header.php b/src/PhpWord/Writer/Word2007/Part/Header.php index 5853d92fe3..b58df1f9df 100644 --- a/src/PhpWord/Writer/Word2007/Part/Header.php +++ b/src/PhpWord/Writer/Word2007/Part/Header.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Part/Numbering.php b/src/PhpWord/Writer/Word2007/Part/Numbering.php index 6233a6b7b1..61e5cc2341 100644 --- a/src/PhpWord/Writer/Word2007/Part/Numbering.php +++ b/src/PhpWord/Writer/Word2007/Part/Numbering.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Part/Rels.php b/src/PhpWord/Writer/Word2007/Part/Rels.php index 154c7e8943..661a4fa862 100644 --- a/src/PhpWord/Writer/Word2007/Part/Rels.php +++ b/src/PhpWord/Writer/Word2007/Part/Rels.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Part/RelsDocument.php b/src/PhpWord/Writer/Word2007/Part/RelsDocument.php index 505aa22382..2a0c5e1117 100644 --- a/src/PhpWord/Writer/Word2007/Part/RelsDocument.php +++ b/src/PhpWord/Writer/Word2007/Part/RelsDocument.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Part/RelsPart.php b/src/PhpWord/Writer/Word2007/Part/RelsPart.php index e639c041cb..ac61a0c2c7 100644 --- a/src/PhpWord/Writer/Word2007/Part/RelsPart.php +++ b/src/PhpWord/Writer/Word2007/Part/RelsPart.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Part/Settings.php b/src/PhpWord/Writer/Word2007/Part/Settings.php index 118c0da069..42d3a5d5ff 100644 --- a/src/PhpWord/Writer/Word2007/Part/Settings.php +++ b/src/PhpWord/Writer/Word2007/Part/Settings.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Part/Styles.php b/src/PhpWord/Writer/Word2007/Part/Styles.php index 03855f03c0..d05338c77d 100644 --- a/src/PhpWord/Writer/Word2007/Part/Styles.php +++ b/src/PhpWord/Writer/Word2007/Part/Styles.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Part/Theme.php b/src/PhpWord/Writer/Word2007/Part/Theme.php index c264140e94..f4ef478ebf 100644 --- a/src/PhpWord/Writer/Word2007/Part/Theme.php +++ b/src/PhpWord/Writer/Word2007/Part/Theme.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Part/WebSettings.php b/src/PhpWord/Writer/Word2007/Part/WebSettings.php index 9f18e3566c..46252e8701 100644 --- a/src/PhpWord/Writer/Word2007/Part/WebSettings.php +++ b/src/PhpWord/Writer/Word2007/Part/WebSettings.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Style/AbstractStyle.php b/src/PhpWord/Writer/Word2007/Style/AbstractStyle.php index d775693351..3236cead0b 100644 --- a/src/PhpWord/Writer/Word2007/Style/AbstractStyle.php +++ b/src/PhpWord/Writer/Word2007/Style/AbstractStyle.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Style/Cell.php b/src/PhpWord/Writer/Word2007/Style/Cell.php index b889aa551e..733b7b434e 100644 --- a/src/PhpWord/Writer/Word2007/Style/Cell.php +++ b/src/PhpWord/Writer/Word2007/Style/Cell.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Style/Extrusion.php b/src/PhpWord/Writer/Word2007/Style/Extrusion.php index e3a86a587c..193993485d 100644 --- a/src/PhpWord/Writer/Word2007/Style/Extrusion.php +++ b/src/PhpWord/Writer/Word2007/Style/Extrusion.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Style/Fill.php b/src/PhpWord/Writer/Word2007/Style/Fill.php index de64313bbf..53d039742b 100644 --- a/src/PhpWord/Writer/Word2007/Style/Fill.php +++ b/src/PhpWord/Writer/Word2007/Style/Fill.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Style/Font.php b/src/PhpWord/Writer/Word2007/Style/Font.php index 5f2a84c0f4..58282d1558 100644 --- a/src/PhpWord/Writer/Word2007/Style/Font.php +++ b/src/PhpWord/Writer/Word2007/Style/Font.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Style/Frame.php b/src/PhpWord/Writer/Word2007/Style/Frame.php index 9bd5db6622..47f9ef758d 100644 --- a/src/PhpWord/Writer/Word2007/Style/Frame.php +++ b/src/PhpWord/Writer/Word2007/Style/Frame.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Style/Image.php b/src/PhpWord/Writer/Word2007/Style/Image.php index 271b99dfec..ef23ed103c 100644 --- a/src/PhpWord/Writer/Word2007/Style/Image.php +++ b/src/PhpWord/Writer/Word2007/Style/Image.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Style/Indentation.php b/src/PhpWord/Writer/Word2007/Style/Indentation.php index c5a598ffb5..961e770fbd 100644 --- a/src/PhpWord/Writer/Word2007/Style/Indentation.php +++ b/src/PhpWord/Writer/Word2007/Style/Indentation.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Style/Line.php b/src/PhpWord/Writer/Word2007/Style/Line.php index f065e52115..154a42c13d 100644 --- a/src/PhpWord/Writer/Word2007/Style/Line.php +++ b/src/PhpWord/Writer/Word2007/Style/Line.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Style/LineNumbering.php b/src/PhpWord/Writer/Word2007/Style/LineNumbering.php index 3ed577c62a..4bf08b65ab 100644 --- a/src/PhpWord/Writer/Word2007/Style/LineNumbering.php +++ b/src/PhpWord/Writer/Word2007/Style/LineNumbering.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Style/MarginBorder.php b/src/PhpWord/Writer/Word2007/Style/MarginBorder.php index 5c3ecde2e2..f5c4b0153b 100644 --- a/src/PhpWord/Writer/Word2007/Style/MarginBorder.php +++ b/src/PhpWord/Writer/Word2007/Style/MarginBorder.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Style/Outline.php b/src/PhpWord/Writer/Word2007/Style/Outline.php index 9ae61f396a..ae4c1da386 100644 --- a/src/PhpWord/Writer/Word2007/Style/Outline.php +++ b/src/PhpWord/Writer/Word2007/Style/Outline.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Style/Paragraph.php b/src/PhpWord/Writer/Word2007/Style/Paragraph.php index eeccc5c87e..6761608608 100644 --- a/src/PhpWord/Writer/Word2007/Style/Paragraph.php +++ b/src/PhpWord/Writer/Word2007/Style/Paragraph.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Style/Row.php b/src/PhpWord/Writer/Word2007/Style/Row.php index f57094db6c..82028d24c4 100644 --- a/src/PhpWord/Writer/Word2007/Style/Row.php +++ b/src/PhpWord/Writer/Word2007/Style/Row.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Style/Section.php b/src/PhpWord/Writer/Word2007/Style/Section.php index ef50c111e5..af77396de1 100644 --- a/src/PhpWord/Writer/Word2007/Style/Section.php +++ b/src/PhpWord/Writer/Word2007/Style/Section.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Style/Shading.php b/src/PhpWord/Writer/Word2007/Style/Shading.php index 0068068791..0f9d6ccc08 100644 --- a/src/PhpWord/Writer/Word2007/Style/Shading.php +++ b/src/PhpWord/Writer/Word2007/Style/Shading.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Style/Shadow.php b/src/PhpWord/Writer/Word2007/Style/Shadow.php index 5efc38c437..7fcb12a960 100644 --- a/src/PhpWord/Writer/Word2007/Style/Shadow.php +++ b/src/PhpWord/Writer/Word2007/Style/Shadow.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Style/Shape.php b/src/PhpWord/Writer/Word2007/Style/Shape.php index aad42ae754..2def6842a9 100644 --- a/src/PhpWord/Writer/Word2007/Style/Shape.php +++ b/src/PhpWord/Writer/Word2007/Style/Shape.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Style/Spacing.php b/src/PhpWord/Writer/Word2007/Style/Spacing.php index c18339bdbb..0185cbcc7a 100644 --- a/src/PhpWord/Writer/Word2007/Style/Spacing.php +++ b/src/PhpWord/Writer/Word2007/Style/Spacing.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Style/Tab.php b/src/PhpWord/Writer/Word2007/Style/Tab.php index 7b0a0ab55d..b41653f6c4 100644 --- a/src/PhpWord/Writer/Word2007/Style/Tab.php +++ b/src/PhpWord/Writer/Word2007/Style/Tab.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Style/Table.php b/src/PhpWord/Writer/Word2007/Style/Table.php index 058e60e2ae..eb5af86da6 100644 --- a/src/PhpWord/Writer/Word2007/Style/Table.php +++ b/src/PhpWord/Writer/Word2007/Style/Table.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Style/TablePosition.php b/src/PhpWord/Writer/Word2007/Style/TablePosition.php index 14fa6a0d58..fa57b93c2f 100644 --- a/src/PhpWord/Writer/Word2007/Style/TablePosition.php +++ b/src/PhpWord/Writer/Word2007/Style/TablePosition.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/Word2007/Style/TextBox.php b/src/PhpWord/Writer/Word2007/Style/TextBox.php index cd92f84550..627d0c86e5 100644 --- a/src/PhpWord/Writer/Word2007/Style/TextBox.php +++ b/src/PhpWord/Writer/Word2007/Style/TextBox.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/src/PhpWord/Writer/WriterInterface.php b/src/PhpWord/Writer/WriterInterface.php index b5f08199d2..499cde3bb1 100644 --- a/src/PhpWord/Writer/WriterInterface.php +++ b/src/PhpWord/Writer/WriterInterface.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Collection/CollectionTest.php b/tests/PhpWord/Collection/CollectionTest.php index a875717110..aba63212a7 100644 --- a/tests/PhpWord/Collection/CollectionTest.php +++ b/tests/PhpWord/Collection/CollectionTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/ComplexType/FootnotePropertiesTest.php b/tests/PhpWord/ComplexType/FootnotePropertiesTest.php index b8df9bbec2..4448daf865 100644 --- a/tests/PhpWord/ComplexType/FootnotePropertiesTest.php +++ b/tests/PhpWord/ComplexType/FootnotePropertiesTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/ComplexType/ProofStateTest.php b/tests/PhpWord/ComplexType/ProofStateTest.php index baf2009e0e..cd1e77f7f0 100644 --- a/tests/PhpWord/ComplexType/ProofStateTest.php +++ b/tests/PhpWord/ComplexType/ProofStateTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/AbstractElementTest.php b/tests/PhpWord/Element/AbstractElementTest.php index 87bb5e18e2..f0531b3433 100644 --- a/tests/PhpWord/Element/AbstractElementTest.php +++ b/tests/PhpWord/Element/AbstractElementTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/BookmarkTest.php b/tests/PhpWord/Element/BookmarkTest.php index bd5d27aec9..04e3f6d547 100644 --- a/tests/PhpWord/Element/BookmarkTest.php +++ b/tests/PhpWord/Element/BookmarkTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/CellTest.php b/tests/PhpWord/Element/CellTest.php index a1132cfad8..d4aaa48888 100644 --- a/tests/PhpWord/Element/CellTest.php +++ b/tests/PhpWord/Element/CellTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/CheckBoxTest.php b/tests/PhpWord/Element/CheckBoxTest.php index d5bda9bd9a..f732407b06 100644 --- a/tests/PhpWord/Element/CheckBoxTest.php +++ b/tests/PhpWord/Element/CheckBoxTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/CommentTest.php b/tests/PhpWord/Element/CommentTest.php index d33a54f629..b9c3dfce5a 100644 --- a/tests/PhpWord/Element/CommentTest.php +++ b/tests/PhpWord/Element/CommentTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/FieldTest.php b/tests/PhpWord/Element/FieldTest.php index 8baa68e475..1c1c0ca1ef 100644 --- a/tests/PhpWord/Element/FieldTest.php +++ b/tests/PhpWord/Element/FieldTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/FooterTest.php b/tests/PhpWord/Element/FooterTest.php index b68e80cd38..9de2487af1 100644 --- a/tests/PhpWord/Element/FooterTest.php +++ b/tests/PhpWord/Element/FooterTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/FootnoteTest.php b/tests/PhpWord/Element/FootnoteTest.php index fd4c8d039e..4ea330f5ac 100644 --- a/tests/PhpWord/Element/FootnoteTest.php +++ b/tests/PhpWord/Element/FootnoteTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/HeaderTest.php b/tests/PhpWord/Element/HeaderTest.php index 29b2fef5fb..e61175f1fa 100644 --- a/tests/PhpWord/Element/HeaderTest.php +++ b/tests/PhpWord/Element/HeaderTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/ImageTest.php b/tests/PhpWord/Element/ImageTest.php index 8bebce9137..747a77ac92 100644 --- a/tests/PhpWord/Element/ImageTest.php +++ b/tests/PhpWord/Element/ImageTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/LineTest.php b/tests/PhpWord/Element/LineTest.php index 4d4149448e..20eee74f38 100644 --- a/tests/PhpWord/Element/LineTest.php +++ b/tests/PhpWord/Element/LineTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/LinkTest.php b/tests/PhpWord/Element/LinkTest.php index 63e8f1de0d..e1be7521a6 100644 --- a/tests/PhpWord/Element/LinkTest.php +++ b/tests/PhpWord/Element/LinkTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/ListItemRunTest.php b/tests/PhpWord/Element/ListItemRunTest.php index 84beec02e4..95eb17eb29 100644 --- a/tests/PhpWord/Element/ListItemRunTest.php +++ b/tests/PhpWord/Element/ListItemRunTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/ListItemTest.php b/tests/PhpWord/Element/ListItemTest.php index 5fae34d468..e5c815ec69 100644 --- a/tests/PhpWord/Element/ListItemTest.php +++ b/tests/PhpWord/Element/ListItemTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/ObjectTest.php b/tests/PhpWord/Element/ObjectTest.php index ba761b70c4..9fbe1bb554 100644 --- a/tests/PhpWord/Element/ObjectTest.php +++ b/tests/PhpWord/Element/ObjectTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/PageBreakTest.php b/tests/PhpWord/Element/PageBreakTest.php index 3b081848cf..d4491fe1b3 100644 --- a/tests/PhpWord/Element/PageBreakTest.php +++ b/tests/PhpWord/Element/PageBreakTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/PreserveTextTest.php b/tests/PhpWord/Element/PreserveTextTest.php index c2767a4f2b..97e49b93df 100644 --- a/tests/PhpWord/Element/PreserveTextTest.php +++ b/tests/PhpWord/Element/PreserveTextTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/RowTest.php b/tests/PhpWord/Element/RowTest.php index 9abf377696..3c53450294 100644 --- a/tests/PhpWord/Element/RowTest.php +++ b/tests/PhpWord/Element/RowTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/SDTTest.php b/tests/PhpWord/Element/SDTTest.php index 41eae2132d..6e40bae011 100644 --- a/tests/PhpWord/Element/SDTTest.php +++ b/tests/PhpWord/Element/SDTTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/SectionTest.php b/tests/PhpWord/Element/SectionTest.php index 37096e2d9e..265307d765 100644 --- a/tests/PhpWord/Element/SectionTest.php +++ b/tests/PhpWord/Element/SectionTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/TOCTest.php b/tests/PhpWord/Element/TOCTest.php index d826a1a158..5f5f518f43 100644 --- a/tests/PhpWord/Element/TOCTest.php +++ b/tests/PhpWord/Element/TOCTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/TableTest.php b/tests/PhpWord/Element/TableTest.php index 0bbefb24f9..8ae5306c82 100644 --- a/tests/PhpWord/Element/TableTest.php +++ b/tests/PhpWord/Element/TableTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/TextBoxTest.php b/tests/PhpWord/Element/TextBoxTest.php index 63b093c924..cd50acd4a6 100644 --- a/tests/PhpWord/Element/TextBoxTest.php +++ b/tests/PhpWord/Element/TextBoxTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/TextBreakTest.php b/tests/PhpWord/Element/TextBreakTest.php index 9b25bac379..13084c679a 100644 --- a/tests/PhpWord/Element/TextBreakTest.php +++ b/tests/PhpWord/Element/TextBreakTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/TextRunTest.php b/tests/PhpWord/Element/TextRunTest.php index 59b8b89fdb..2168bcc49a 100644 --- a/tests/PhpWord/Element/TextRunTest.php +++ b/tests/PhpWord/Element/TextRunTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/TextTest.php b/tests/PhpWord/Element/TextTest.php index 09027ad6cf..97be7ae5b6 100644 --- a/tests/PhpWord/Element/TextTest.php +++ b/tests/PhpWord/Element/TextTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/TitleTest.php b/tests/PhpWord/Element/TitleTest.php index e99a80a63d..6ef87c3e8e 100644 --- a/tests/PhpWord/Element/TitleTest.php +++ b/tests/PhpWord/Element/TitleTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Element/TrackChangeTest.php b/tests/PhpWord/Element/TrackChangeTest.php index 3249f10be3..df86feb22f 100644 --- a/tests/PhpWord/Element/TrackChangeTest.php +++ b/tests/PhpWord/Element/TrackChangeTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Exception/CopyFileExceptionTest.php b/tests/PhpWord/Exception/CopyFileExceptionTest.php index fa9949ed7f..5fed9c9f25 100644 --- a/tests/PhpWord/Exception/CopyFileExceptionTest.php +++ b/tests/PhpWord/Exception/CopyFileExceptionTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Exception/CreateTemporaryFileExceptionTest.php b/tests/PhpWord/Exception/CreateTemporaryFileExceptionTest.php index 6b4d14bf01..f879285e89 100644 --- a/tests/PhpWord/Exception/CreateTemporaryFileExceptionTest.php +++ b/tests/PhpWord/Exception/CreateTemporaryFileExceptionTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Exception/ExceptionTest.php b/tests/PhpWord/Exception/ExceptionTest.php index 255477f91e..8c7bce5774 100644 --- a/tests/PhpWord/Exception/ExceptionTest.php +++ b/tests/PhpWord/Exception/ExceptionTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Exception/InvalidImageExceptionTest.php b/tests/PhpWord/Exception/InvalidImageExceptionTest.php index c0285dc14f..71da1aa9e3 100644 --- a/tests/PhpWord/Exception/InvalidImageExceptionTest.php +++ b/tests/PhpWord/Exception/InvalidImageExceptionTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Exception/InvalidStyleExceptionTest.php b/tests/PhpWord/Exception/InvalidStyleExceptionTest.php index d516019f63..1d981449a9 100644 --- a/tests/PhpWord/Exception/InvalidStyleExceptionTest.php +++ b/tests/PhpWord/Exception/InvalidStyleExceptionTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Exception/UnsupportedImageTypeExceptionTest.php b/tests/PhpWord/Exception/UnsupportedImageTypeExceptionTest.php index 559d63412e..5b03f5e31d 100644 --- a/tests/PhpWord/Exception/UnsupportedImageTypeExceptionTest.php +++ b/tests/PhpWord/Exception/UnsupportedImageTypeExceptionTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/IOFactoryTest.php b/tests/PhpWord/IOFactoryTest.php index 581b7d49de..4a59e7022a 100644 --- a/tests/PhpWord/IOFactoryTest.php +++ b/tests/PhpWord/IOFactoryTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/MediaTest.php b/tests/PhpWord/MediaTest.php index ed56376b4a..0249201684 100644 --- a/tests/PhpWord/MediaTest.php +++ b/tests/PhpWord/MediaTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Metadata/DocInfoTest.php b/tests/PhpWord/Metadata/DocInfoTest.php index d9b44dc631..25a323d2f2 100644 --- a/tests/PhpWord/Metadata/DocInfoTest.php +++ b/tests/PhpWord/Metadata/DocInfoTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Metadata/SettingsTest.php b/tests/PhpWord/Metadata/SettingsTest.php index 07dc896291..9670f1d992 100644 --- a/tests/PhpWord/Metadata/SettingsTest.php +++ b/tests/PhpWord/Metadata/SettingsTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/PhpWordTest.php b/tests/PhpWord/PhpWordTest.php index 3b1b5a3611..d818e0f8bb 100644 --- a/tests/PhpWord/PhpWordTest.php +++ b/tests/PhpWord/PhpWordTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Reader/HTMLTest.php b/tests/PhpWord/Reader/HTMLTest.php index c56fc1fc91..38588afc17 100644 --- a/tests/PhpWord/Reader/HTMLTest.php +++ b/tests/PhpWord/Reader/HTMLTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Reader/MsDocTest.php b/tests/PhpWord/Reader/MsDocTest.php index e407547d75..3ce3993977 100644 --- a/tests/PhpWord/Reader/MsDocTest.php +++ b/tests/PhpWord/Reader/MsDocTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Reader/ODTextTest.php b/tests/PhpWord/Reader/ODTextTest.php index 7041e13eb6..ad27086495 100644 --- a/tests/PhpWord/Reader/ODTextTest.php +++ b/tests/PhpWord/Reader/ODTextTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Reader/RTFTest.php b/tests/PhpWord/Reader/RTFTest.php index ca1f6ed49b..fed00ceb36 100644 --- a/tests/PhpWord/Reader/RTFTest.php +++ b/tests/PhpWord/Reader/RTFTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Reader/Word2007/ElementTest.php b/tests/PhpWord/Reader/Word2007/ElementTest.php index 10c1ec9a15..941e6f8295 100644 --- a/tests/PhpWord/Reader/Word2007/ElementTest.php +++ b/tests/PhpWord/Reader/Word2007/ElementTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Reader/Word2007/PartTest.php b/tests/PhpWord/Reader/Word2007/PartTest.php index 0f7ecc7c90..31a492b8c2 100644 --- a/tests/PhpWord/Reader/Word2007/PartTest.php +++ b/tests/PhpWord/Reader/Word2007/PartTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Reader/Word2007/StyleTest.php b/tests/PhpWord/Reader/Word2007/StyleTest.php index 3b04b6770a..46421d97a7 100644 --- a/tests/PhpWord/Reader/Word2007/StyleTest.php +++ b/tests/PhpWord/Reader/Word2007/StyleTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Reader/Word2007Test.php b/tests/PhpWord/Reader/Word2007Test.php index 9a555672f9..62d23a6873 100644 --- a/tests/PhpWord/Reader/Word2007Test.php +++ b/tests/PhpWord/Reader/Word2007Test.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/SettingsTest.php b/tests/PhpWord/SettingsTest.php index d8752b2b7c..afe5954969 100644 --- a/tests/PhpWord/SettingsTest.php +++ b/tests/PhpWord/SettingsTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Shared/ConverterTest.php b/tests/PhpWord/Shared/ConverterTest.php index 752b9a8a1b..3798a07b1d 100644 --- a/tests/PhpWord/Shared/ConverterTest.php +++ b/tests/PhpWord/Shared/ConverterTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index 8be1cc191c..7541c9c460 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Shared/Microsoft/PasswordEncoderTest.php b/tests/PhpWord/Shared/Microsoft/PasswordEncoderTest.php index c42a6eb4f6..5a050c54e5 100644 --- a/tests/PhpWord/Shared/Microsoft/PasswordEncoderTest.php +++ b/tests/PhpWord/Shared/Microsoft/PasswordEncoderTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Shared/ZipArchiveTest.php b/tests/PhpWord/Shared/ZipArchiveTest.php index cb095127a6..ecd0961e24 100644 --- a/tests/PhpWord/Shared/ZipArchiveTest.php +++ b/tests/PhpWord/Shared/ZipArchiveTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Style/AbstractStyleTest.php b/tests/PhpWord/Style/AbstractStyleTest.php index c0263b1bea..7ec272bb9b 100644 --- a/tests/PhpWord/Style/AbstractStyleTest.php +++ b/tests/PhpWord/Style/AbstractStyleTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Style/CellTest.php b/tests/PhpWord/Style/CellTest.php index 79b22ee1b4..db789fdcef 100644 --- a/tests/PhpWord/Style/CellTest.php +++ b/tests/PhpWord/Style/CellTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Style/FontTest.php b/tests/PhpWord/Style/FontTest.php index 91bba97fa1..4ddbd39793 100644 --- a/tests/PhpWord/Style/FontTest.php +++ b/tests/PhpWord/Style/FontTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Style/ImageTest.php b/tests/PhpWord/Style/ImageTest.php index 5d9e556892..09287bb9a4 100644 --- a/tests/PhpWord/Style/ImageTest.php +++ b/tests/PhpWord/Style/ImageTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Style/IndentationTest.php b/tests/PhpWord/Style/IndentationTest.php index 63a9662866..b39a4d771d 100644 --- a/tests/PhpWord/Style/IndentationTest.php +++ b/tests/PhpWord/Style/IndentationTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Style/LanguageTest.php b/tests/PhpWord/Style/LanguageTest.php index 74b2067a20..99741cea51 100644 --- a/tests/PhpWord/Style/LanguageTest.php +++ b/tests/PhpWord/Style/LanguageTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Style/LineNumberingTest.php b/tests/PhpWord/Style/LineNumberingTest.php index 9ec1e3b741..0d3f4e0563 100644 --- a/tests/PhpWord/Style/LineNumberingTest.php +++ b/tests/PhpWord/Style/LineNumberingTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Style/LineTest.php b/tests/PhpWord/Style/LineTest.php index ab77b32814..fba09f708d 100644 --- a/tests/PhpWord/Style/LineTest.php +++ b/tests/PhpWord/Style/LineTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Style/ListItemTest.php b/tests/PhpWord/Style/ListItemTest.php index a8155fa328..71598e8030 100644 --- a/tests/PhpWord/Style/ListItemTest.php +++ b/tests/PhpWord/Style/ListItemTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Style/NumberingLevelTest.php b/tests/PhpWord/Style/NumberingLevelTest.php index 9b512eb024..008a1fc5b5 100644 --- a/tests/PhpWord/Style/NumberingLevelTest.php +++ b/tests/PhpWord/Style/NumberingLevelTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Style/NumberingTest.php b/tests/PhpWord/Style/NumberingTest.php index 4ec1236626..2090f9f6fc 100644 --- a/tests/PhpWord/Style/NumberingTest.php +++ b/tests/PhpWord/Style/NumberingTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Style/PaperTest.php b/tests/PhpWord/Style/PaperTest.php index 687e23c647..688f31afe2 100644 --- a/tests/PhpWord/Style/PaperTest.php +++ b/tests/PhpWord/Style/PaperTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Style/ParagraphTest.php b/tests/PhpWord/Style/ParagraphTest.php index adf0ed4d30..624607381e 100644 --- a/tests/PhpWord/Style/ParagraphTest.php +++ b/tests/PhpWord/Style/ParagraphTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Style/RowTest.php b/tests/PhpWord/Style/RowTest.php index 2daad7ea2a..534815b1b4 100644 --- a/tests/PhpWord/Style/RowTest.php +++ b/tests/PhpWord/Style/RowTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Style/SectionTest.php b/tests/PhpWord/Style/SectionTest.php index c9b7003f95..b26d1d94c8 100644 --- a/tests/PhpWord/Style/SectionTest.php +++ b/tests/PhpWord/Style/SectionTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Style/ShadingTest.php b/tests/PhpWord/Style/ShadingTest.php index ab991a5753..7aba03a122 100644 --- a/tests/PhpWord/Style/ShadingTest.php +++ b/tests/PhpWord/Style/ShadingTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Style/SpacingTest.php b/tests/PhpWord/Style/SpacingTest.php index 65be8092ef..f7402edd12 100644 --- a/tests/PhpWord/Style/SpacingTest.php +++ b/tests/PhpWord/Style/SpacingTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Style/TOCTest.php b/tests/PhpWord/Style/TOCTest.php index 5981b00c6d..445c5e4315 100644 --- a/tests/PhpWord/Style/TOCTest.php +++ b/tests/PhpWord/Style/TOCTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Style/TabTest.php b/tests/PhpWord/Style/TabTest.php index c11f0558bd..8d8d3f6cf0 100644 --- a/tests/PhpWord/Style/TabTest.php +++ b/tests/PhpWord/Style/TabTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Style/TableTest.php b/tests/PhpWord/Style/TableTest.php index 1ee718df68..332d31aac8 100644 --- a/tests/PhpWord/Style/TableTest.php +++ b/tests/PhpWord/Style/TableTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Style/TextBoxTest.php b/tests/PhpWord/Style/TextBoxTest.php index 5a6bc76fb4..803189cd19 100644 --- a/tests/PhpWord/Style/TextBoxTest.php +++ b/tests/PhpWord/Style/TextBoxTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/StyleTest.php b/tests/PhpWord/StyleTest.php index 6f2f09800b..cbc39c871e 100644 --- a/tests/PhpWord/StyleTest.php +++ b/tests/PhpWord/StyleTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/TemplateProcessorTest.php b/tests/PhpWord/TemplateProcessorTest.php index 7b064ef7b8..c762a6096e 100644 --- a/tests/PhpWord/TemplateProcessorTest.php +++ b/tests/PhpWord/TemplateProcessorTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/HTML/ElementTest.php b/tests/PhpWord/Writer/HTML/ElementTest.php index fc092ba313..ff79953c32 100644 --- a/tests/PhpWord/Writer/HTML/ElementTest.php +++ b/tests/PhpWord/Writer/HTML/ElementTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/HTML/PartTest.php b/tests/PhpWord/Writer/HTML/PartTest.php index 3d56f9834d..f83034143c 100644 --- a/tests/PhpWord/Writer/HTML/PartTest.php +++ b/tests/PhpWord/Writer/HTML/PartTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/HTML/StyleTest.php b/tests/PhpWord/Writer/HTML/StyleTest.php index e9117de9b6..5b60226c3f 100644 --- a/tests/PhpWord/Writer/HTML/StyleTest.php +++ b/tests/PhpWord/Writer/HTML/StyleTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/HTMLTest.php b/tests/PhpWord/Writer/HTMLTest.php index f2bc717583..8868db5a58 100644 --- a/tests/PhpWord/Writer/HTMLTest.php +++ b/tests/PhpWord/Writer/HTMLTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/ODText/ElementTest.php b/tests/PhpWord/Writer/ODText/ElementTest.php index f56114ea15..37f0d1ef52 100644 --- a/tests/PhpWord/Writer/ODText/ElementTest.php +++ b/tests/PhpWord/Writer/ODText/ElementTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/ODText/Part/AbstractPartTest.php b/tests/PhpWord/Writer/ODText/Part/AbstractPartTest.php index f91e6dd281..51d893d23e 100644 --- a/tests/PhpWord/Writer/ODText/Part/AbstractPartTest.php +++ b/tests/PhpWord/Writer/ODText/Part/AbstractPartTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/ODText/Part/ContentTest.php b/tests/PhpWord/Writer/ODText/Part/ContentTest.php index d568114313..2e501c6024 100644 --- a/tests/PhpWord/Writer/ODText/Part/ContentTest.php +++ b/tests/PhpWord/Writer/ODText/Part/ContentTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/ODText/StyleTest.php b/tests/PhpWord/Writer/ODText/StyleTest.php index 5bd862f950..b1bf417d59 100644 --- a/tests/PhpWord/Writer/ODText/StyleTest.php +++ b/tests/PhpWord/Writer/ODText/StyleTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/ODTextTest.php b/tests/PhpWord/Writer/ODTextTest.php index 1984de0f07..a576a68d60 100644 --- a/tests/PhpWord/Writer/ODTextTest.php +++ b/tests/PhpWord/Writer/ODTextTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/PDF/DomPDFTest.php b/tests/PhpWord/Writer/PDF/DomPDFTest.php index 61c3d2963e..bc229d5186 100644 --- a/tests/PhpWord/Writer/PDF/DomPDFTest.php +++ b/tests/PhpWord/Writer/PDF/DomPDFTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/PDF/MPDFTest.php b/tests/PhpWord/Writer/PDF/MPDFTest.php index 330125fb3f..34a5f8d86b 100644 --- a/tests/PhpWord/Writer/PDF/MPDFTest.php +++ b/tests/PhpWord/Writer/PDF/MPDFTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/PDF/TCPDFTest.php b/tests/PhpWord/Writer/PDF/TCPDFTest.php index e697eee1a8..6dc8f24cb7 100644 --- a/tests/PhpWord/Writer/PDF/TCPDFTest.php +++ b/tests/PhpWord/Writer/PDF/TCPDFTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/PDFTest.php b/tests/PhpWord/Writer/PDFTest.php index a7ca9f68ad..f699385c8c 100644 --- a/tests/PhpWord/Writer/PDFTest.php +++ b/tests/PhpWord/Writer/PDFTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/RTF/ElementTest.php b/tests/PhpWord/Writer/RTF/ElementTest.php index e85d20918a..47630335a3 100644 --- a/tests/PhpWord/Writer/RTF/ElementTest.php +++ b/tests/PhpWord/Writer/RTF/ElementTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/RTF/StyleTest.php b/tests/PhpWord/Writer/RTF/StyleTest.php index 42f76430c2..5f04f1a815 100644 --- a/tests/PhpWord/Writer/RTF/StyleTest.php +++ b/tests/PhpWord/Writer/RTF/StyleTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/RTFTest.php b/tests/PhpWord/Writer/RTFTest.php index 803087e567..010720bd12 100644 --- a/tests/PhpWord/Writer/RTFTest.php +++ b/tests/PhpWord/Writer/RTFTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/Word2007/ElementTest.php b/tests/PhpWord/Writer/Word2007/ElementTest.php index b59e369f5d..979a4337ba 100644 --- a/tests/PhpWord/Writer/Word2007/ElementTest.php +++ b/tests/PhpWord/Writer/Word2007/ElementTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/Word2007/Part/AbstractPartTest.php b/tests/PhpWord/Writer/Word2007/Part/AbstractPartTest.php index 7796c02cda..fac94882d2 100644 --- a/tests/PhpWord/Writer/Word2007/Part/AbstractPartTest.php +++ b/tests/PhpWord/Writer/Word2007/Part/AbstractPartTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/Word2007/Part/CommentsTest.php b/tests/PhpWord/Writer/Word2007/Part/CommentsTest.php index 83af284f23..0233abdf2e 100644 --- a/tests/PhpWord/Writer/Word2007/Part/CommentsTest.php +++ b/tests/PhpWord/Writer/Word2007/Part/CommentsTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/Word2007/Part/DocumentTest.php b/tests/PhpWord/Writer/Word2007/Part/DocumentTest.php index 39db602885..b35f932770 100644 --- a/tests/PhpWord/Writer/Word2007/Part/DocumentTest.php +++ b/tests/PhpWord/Writer/Word2007/Part/DocumentTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/Word2007/Part/FooterTest.php b/tests/PhpWord/Writer/Word2007/Part/FooterTest.php index 82bb7b7de0..1f9bba0dd0 100644 --- a/tests/PhpWord/Writer/Word2007/Part/FooterTest.php +++ b/tests/PhpWord/Writer/Word2007/Part/FooterTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/Word2007/Part/FootnotesTest.php b/tests/PhpWord/Writer/Word2007/Part/FootnotesTest.php index 3d11174a27..4b0e94df30 100644 --- a/tests/PhpWord/Writer/Word2007/Part/FootnotesTest.php +++ b/tests/PhpWord/Writer/Word2007/Part/FootnotesTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/Word2007/Part/HeaderTest.php b/tests/PhpWord/Writer/Word2007/Part/HeaderTest.php index afa81cf9b3..9edd0063bd 100644 --- a/tests/PhpWord/Writer/Word2007/Part/HeaderTest.php +++ b/tests/PhpWord/Writer/Word2007/Part/HeaderTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/Word2007/Part/NumberingTest.php b/tests/PhpWord/Writer/Word2007/Part/NumberingTest.php index 62127e294b..fb5a220e88 100644 --- a/tests/PhpWord/Writer/Word2007/Part/NumberingTest.php +++ b/tests/PhpWord/Writer/Word2007/Part/NumberingTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php b/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php index a8c01da010..8201d746a0 100644 --- a/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php +++ b/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/Word2007/Part/StylesTest.php b/tests/PhpWord/Writer/Word2007/Part/StylesTest.php index 0cdb444e33..91f371841d 100644 --- a/tests/PhpWord/Writer/Word2007/Part/StylesTest.php +++ b/tests/PhpWord/Writer/Word2007/Part/StylesTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/Word2007/PartTest.php b/tests/PhpWord/Writer/Word2007/PartTest.php index 160bf55355..277f61e1be 100644 --- a/tests/PhpWord/Writer/Word2007/PartTest.php +++ b/tests/PhpWord/Writer/Word2007/PartTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/Word2007/Style/FontTest.php b/tests/PhpWord/Writer/Word2007/Style/FontTest.php index f66cf24ff4..c57f50ab54 100644 --- a/tests/PhpWord/Writer/Word2007/Style/FontTest.php +++ b/tests/PhpWord/Writer/Word2007/Style/FontTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/Word2007/Style/ParagraphTest.php b/tests/PhpWord/Writer/Word2007/Style/ParagraphTest.php index 1e5e1d13c7..8443bbcaad 100644 --- a/tests/PhpWord/Writer/Word2007/Style/ParagraphTest.php +++ b/tests/PhpWord/Writer/Word2007/Style/ParagraphTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/Word2007/Style/TableTest.php b/tests/PhpWord/Writer/Word2007/Style/TableTest.php index 2b67507a94..364a34d63b 100644 --- a/tests/PhpWord/Writer/Word2007/Style/TableTest.php +++ b/tests/PhpWord/Writer/Word2007/Style/TableTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/Word2007/StyleTest.php b/tests/PhpWord/Writer/Word2007/StyleTest.php index f48597d26d..48cff8713a 100644 --- a/tests/PhpWord/Writer/Word2007/StyleTest.php +++ b/tests/PhpWord/Writer/Word2007/StyleTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/Writer/Word2007Test.php b/tests/PhpWord/Writer/Word2007Test.php index 3e1edb39e4..22a0e6dfdb 100644 --- a/tests/PhpWord/Writer/Word2007Test.php +++ b/tests/PhpWord/Writer/Word2007Test.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/_includes/AbstractTestReader.php b/tests/PhpWord/_includes/AbstractTestReader.php index 348cab98af..d9097d717f 100644 --- a/tests/PhpWord/_includes/AbstractTestReader.php +++ b/tests/PhpWord/_includes/AbstractTestReader.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/_includes/TestHelperDOCX.php b/tests/PhpWord/_includes/TestHelperDOCX.php index bef060eeaf..02fa7d78a8 100644 --- a/tests/PhpWord/_includes/TestHelperDOCX.php +++ b/tests/PhpWord/_includes/TestHelperDOCX.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/PhpWord/_includes/XmlDocument.php b/tests/PhpWord/_includes/XmlDocument.php index 21a12105c2..8c937bf5a0 100644 --- a/tests/PhpWord/_includes/XmlDocument.php +++ b/tests/PhpWord/_includes/XmlDocument.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 7126c20415..c1681bcd6f 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. test bootstrap * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ require_once __DIR__ . '/../bootstrap.php'; From e29a3e7c103c29867d855b75a98134ae48fa4072 Mon Sep 17 00:00:00 2001 From: troosan Date: Sun, 11 Mar 2018 13:27:35 +0100 Subject: [PATCH 055/135] add text wrapping distance --- samples/Sample_13_Images.php | 38 ++++-- src/PhpWord/Style/Frame.php | 120 ++++++++++++++++++ src/PhpWord/Writer/Word2007/Style/Frame.php | 13 +- tests/PhpWord/Style/FontTest.php | 1 + tests/PhpWord/Style/ImageTest.php | 41 +++--- tests/PhpWord/Writer/HTML/ElementTest.php | 23 ++++ .../Writer/Word2007/Style/ImageTest.php | 69 ++++++++++ 7 files changed, 272 insertions(+), 33 deletions(-) create mode 100644 tests/PhpWord/Writer/Word2007/Style/ImageTest.php diff --git a/samples/Sample_13_Images.php b/samples/Sample_13_Images.php index 6c7033b048..f7be3be969 100644 --- a/samples/Sample_13_Images.php +++ b/samples/Sample_13_Images.php @@ -1,4 +1,7 @@ addSection(); $section->addText('Local image without any styles:'); $section->addImage('resources/_mars.jpg'); -$section->addTextBreak(2); +printSeparator($section); $section->addText('Local image with styles:'); $section->addImage('resources/_earth.jpg', array('width' => 210, 'height' => 210, 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER)); -$section->addTextBreak(2); // Remote image +printSeparator($section); $source = 'http://php.net/images/logos/php-med-trans-light.gif'; $section->addText("Remote image from: {$source}"); $section->addImage($source); // Image from string +printSeparator($section); $source = 'resources/_mars.jpg'; $fileContent = file_get_contents($source); $section->addText('Image from string'); $section->addImage($fileContent); //Wrapping style -$text = str_repeat('Hello World! ', 15); +printSeparator($section); +$text = str_repeat('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. ', 2); $wrappingStyles = array('inline', 'behind', 'infront', 'square', 'tight'); foreach ($wrappingStyles as $wrappingStyle) { - $section->addTextBreak(5); $section->addText("Wrapping style {$wrappingStyle}"); $section->addImage( 'resources/_earth.jpg', array( - 'positioning' => 'relative', - 'marginTop' => -1, - 'marginLeft' => 1, - 'width' => 80, - 'height' => 80, - 'wrappingStyle' => $wrappingStyle, + 'positioning' => 'relative', + 'marginTop' => -1, + 'marginLeft' => 1, + 'width' => 80, + 'height' => 80, + 'wrappingStyle' => $wrappingStyle, + 'wrapDistanceRight' => Converter::cmToPoint(1), + 'wrapDistanceBottom' => Converter::cmToPoint(1), ) ); $section->addText($text); + printSeparator($section); } //Absolute positioning -$section->addTextBreak(3); $section->addText('Absolute positioning: see top right corner of page'); $section->addImage( 'resources/_mars.jpg', @@ -64,7 +70,7 @@ ); //Relative positioning -$section->addTextBreak(3); +printSeparator($section); $section->addText('Relative positioning: Horizontal position center relative to column,'); $section->addText('Vertical position top relative to line'); $section->addImage( @@ -80,6 +86,14 @@ ) ); +function printSeparator(Section $section) +{ + $section->addTextBreak(); + $lineStyle = array('weight' => 0.2, 'width' => 150, 'height' => 0, 'align' => 'center'); + $section->addLine($lineStyle); + $section->addTextBreak(2); +} + // Save file echo write($phpWord, basename(__FILE__, '.php'), $writers); if (!CLI) { diff --git a/src/PhpWord/Style/Frame.php b/src/PhpWord/Style/Frame.php index b926304902..e87b7a803a 100644 --- a/src/PhpWord/Style/Frame.php +++ b/src/PhpWord/Style/Frame.php @@ -171,6 +171,34 @@ class Frame extends AbstractStyle */ private $wrap; + /** + * Top wrap distance + * + * @var float + */ + private $wrapDistanceTop; + + /** + * Bottom wrap distance + * + * @var float + */ + private $wrapDistanceBottom; + + /** + * Left wrap distance + * + * @var float + */ + private $wrapDistanceLeft; + + /** + * Right wrap distance + * + * @var float + */ + private $wrapDistanceRight; + /** * Vertically raised or lowered text * @@ -547,6 +575,98 @@ public function setWrap($value) return $this; } + /** + * Get top distance from text wrap + * + * @return float + */ + public function getWrapDistanceTop() + { + return $this->wrapDistanceTop; + } + + /** + * Set top distance from text wrap + * + * @param int $value + * @return self + */ + public function setWrapDistanceTop($value = null) + { + $this->wrapDistanceTop = $this->setFloatVal($value, null); + + return $this; + } + + /** + * Get bottom distance from text wrap + * + * @return float + */ + public function getWrapDistanceBottom() + { + return $this->wrapDistanceBottom; + } + + /** + * Set bottom distance from text wrap + * + * @param float $value + * @return self + */ + public function setWrapDistanceBottom($value = null) + { + $this->wrapDistanceBottom = $this->setFloatVal($value, null); + + return $this; + } + + /** + * Get left distance from text wrap + * + * @return float + */ + public function getWrapDistanceLeft() + { + return $this->wrapDistanceLeft; + } + + /** + * Set left distance from text wrap + * + * @param float $value + * @return self + */ + public function setWrapDistanceLeft($value = null) + { + $this->wrapDistanceLeft = $this->setFloatVal($value, null); + + return $this; + } + + /** + * Get right distance from text wrap + * + * @return float + */ + public function getWrapDistanceRight() + { + return $this->wrapDistanceRight; + } + + /** + * Set right distance from text wrap + * + * @param float $value + * @return self + */ + public function setWrapDistanceRight($value = null) + { + $this->wrapDistanceRight = $this->setFloatVal($value, null); + + return $this; + } + /** * Get position * diff --git a/src/PhpWord/Writer/Word2007/Style/Frame.php b/src/PhpWord/Writer/Word2007/Style/Frame.php index 47f9ef758d..ea5abf780a 100644 --- a/src/PhpWord/Writer/Word2007/Style/Frame.php +++ b/src/PhpWord/Writer/Word2007/Style/Frame.php @@ -45,10 +45,14 @@ public function write() $zIndices = array(FrameStyle::WRAP_INFRONT => $maxZIndex, FrameStyle::WRAP_BEHIND => -$maxZIndex); $properties = array( - 'width' => 'width', - 'height' => 'height', - 'left' => 'margin-left', - 'top' => 'margin-top', + 'width' => 'width', + 'height' => 'height', + 'left' => 'margin-left', + 'top' => 'margin-top', + 'wrapDistanceTop' => 'mso-wrap-distance-top', + 'wrapDistanceBottom' => 'mso-wrap-distance-bottom', + 'wrapDistanceLeft' => 'mso-wrap-distance-left', + 'wrapDistanceRight' => 'mso-wrap-distance-right', ); $sizeStyles = $this->getStyles($style, $properties, $style->getUnit()); @@ -57,7 +61,6 @@ public function write() 'hPos' => 'mso-position-horizontal', 'vPos' => 'mso-position-vertical', 'hPosRelTo' => 'mso-position-horizontal-relative', - 'vPosRelTo' => 'mso-position-vertical-relative', ); $posStyles = $this->getStyles($style, $properties); diff --git a/tests/PhpWord/Style/FontTest.php b/tests/PhpWord/Style/FontTest.php index 4ddbd39793..6a934579ae 100644 --- a/tests/PhpWord/Style/FontTest.php +++ b/tests/PhpWord/Style/FontTest.php @@ -115,6 +115,7 @@ public function testSetStyleValueNormal() 'spacing' => 240, 'kerning' => 10, 'rtl' => true, + 'noProof' => true, 'lang' => new Language(Language::EN_US), ); $object->setStyleByArray($attributes); diff --git a/tests/PhpWord/Style/ImageTest.php b/tests/PhpWord/Style/ImageTest.php index 09287bb9a4..1d43d92152 100644 --- a/tests/PhpWord/Style/ImageTest.php +++ b/tests/PhpWord/Style/ImageTest.php @@ -35,12 +35,16 @@ public function testSetGetNormal() $object = new Image(); $properties = array( - 'width' => 200, - 'height' => 200, - 'alignment' => Jc::START, - 'marginTop' => 240, - 'marginLeft' => 240, - 'wrappingStyle' => 'inline', + 'width' => 200, + 'height' => 200, + 'alignment' => Jc::START, + 'marginTop' => 240, + 'marginLeft' => 240, + 'wrappingStyle' => 'inline', + 'wrapDistanceLeft' => 10, + 'wrapDistanceRight' => 20, + 'wrapDistanceTop' => 30, + 'wrapDistanceBottom' => 40, ); foreach ($properties as $key => $value) { $set = "set{$key}"; @@ -58,16 +62,21 @@ public function testSetStyleValue() $object = new Image(); $properties = array( - 'width' => 200, - 'height' => 200, - 'alignment' => Jc::START, - 'marginTop' => 240, - 'marginLeft' => 240, - 'positioning' => \PhpOffice\PhpWord\Style\Image::POSITION_ABSOLUTE, - 'posHorizontal' => \PhpOffice\PhpWord\Style\Image::POSITION_HORIZONTAL_CENTER, - 'posVertical' => \PhpOffice\PhpWord\Style\Image::POSITION_VERTICAL_TOP, - 'posHorizontalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_COLUMN, - 'posVerticalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_IMARGIN, + 'width' => 200, + 'height' => 200, + 'alignment' => Jc::START, + 'marginTop' => 240, + 'marginLeft' => 240, + 'position' => 10, + 'positioning' => \PhpOffice\PhpWord\Style\Image::POSITION_ABSOLUTE, + 'posHorizontal' => \PhpOffice\PhpWord\Style\Image::POSITION_HORIZONTAL_CENTER, + 'posVertical' => \PhpOffice\PhpWord\Style\Image::POSITION_VERTICAL_TOP, + 'posHorizontalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_COLUMN, + 'posVerticalRel' => \PhpOffice\PhpWord\Style\Image::POSITION_RELATIVE_TO_IMARGIN, + 'wrapDistanceLeft' => 10, + 'wrapDistanceRight' => 20, + 'wrapDistanceTop' => 30, + 'wrapDistanceBottom' => 40, ); foreach ($properties as $key => $value) { $get = "get{$key}"; diff --git a/tests/PhpWord/Writer/HTML/ElementTest.php b/tests/PhpWord/Writer/HTML/ElementTest.php index ff79953c32..ceb3abcbdb 100644 --- a/tests/PhpWord/Writer/HTML/ElementTest.php +++ b/tests/PhpWord/Writer/HTML/ElementTest.php @@ -17,7 +17,9 @@ namespace PhpOffice\PhpWord\Writer\HTML; +use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Element\Text as TextElement; +use PhpOffice\PhpWord\Element\TrackChange; use PhpOffice\PhpWord\Writer\HTML; use PhpOffice\PhpWord\Writer\HTML\Element\Text; @@ -54,4 +56,25 @@ public function testWriteTextElement() $this->assertEquals(htmlspecialchars('-A-', ENT_COMPAT, 'UTF-8'), $object->write()); } + + /** + * Test write TrackChange + */ + public function testWriteTrackChanges() + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $text = $section->addText('my dummy text'); + $text->setChangeInfo(TrackChange::INSERTED, 'author name'); + $text2 = $section->addText('my other text'); + $text2->setTrackChange(new TrackChange(TrackChange::DELETED, 'another author', new \DateTime())); + + $htmlWriter = new HTML($phpWord); + $dom = new \DOMDocument(); + $dom->loadHTML($htmlWriter->getContent()); + $xpath = new \DOMXpath($dom); + + $this->assertTrue($xpath->query('/html/body/p[1]/ins')->length == 1); + $this->assertTrue($xpath->query('/html/body/p[2]/del')->length == 1); + } } diff --git a/tests/PhpWord/Writer/Word2007/Style/ImageTest.php b/tests/PhpWord/Writer/Word2007/Style/ImageTest.php new file mode 100644 index 0000000000..efa0a10534 --- /dev/null +++ b/tests/PhpWord/Writer/Word2007/Style/ImageTest.php @@ -0,0 +1,69 @@ + Image::WRAP_INLINE, + 'wrapDistanceLeft' => 10, + 'wrapDistanceRight' => 20, + 'wrapDistanceTop' => 30, + 'wrapDistanceBottom' => 40, + ); + + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + $section->addImage(__DIR__ . '/../../../_files/images/earth.jpg', $styles); + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $path = '/w:document/w:body/w:p[1]/w:r/w:pict/v:shape'; + $this->assertTrue($doc->elementExists($path . '/w10:wrap')); + $this->assertEquals('inline', $doc->getElementAttribute($path . '/w10:wrap', 'type')); + + $this->assertTrue($doc->elementExists($path)); + $style = $doc->getElement($path)->getAttribute('style'); + $this->assertNotNull($style); + $this->assertContains('mso-wrap-distance-left:10pt;', $style); + $this->assertContains('mso-wrap-distance-right:20pt;', $style); + $this->assertContains('mso-wrap-distance-top:30pt;', $style); + $this->assertContains('mso-wrap-distance-bottom:40pt;', $style); + } +} From a0111be6ae1e5bc2018f171b34849975ce59d579 Mon Sep 17 00:00:00 2001 From: troosan Date: Sun, 11 Mar 2018 15:02:24 +0100 Subject: [PATCH 056/135] update changelog and doc --- CHANGELOG.md | 1 + docs/styles.rst | 4 ++++ tests/PhpWord/Writer/HTML/ElementTest.php | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c83ac35aa..e4515131ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ v0.15.0 (?? ??? 2018) - Add support for MACROBUTTON field @phryneas @troosan #1021 - Add support for Hyphenation @Trainmaster #1282 (Document: `autoHyphenation`, `consecutiveHyphenLimit`, `hyphenationZone`, `doNotHyphenateCaps`, Paragraph: `suppressAutoHyphens`) - Added support for Floating Table Positioning (tblpPr) @anrikun #639 +- Added support for Image text wrapping distance @troosan #1310 ### Fixed - Fix reading of docx default style - @troosan #1238 diff --git a/docs/styles.rst b/docs/styles.rst index 98088e7826..9b3ce75819 100644 --- a/docs/styles.rst +++ b/docs/styles.rst @@ -154,6 +154,10 @@ Available Image style options: - ``marginTop``. Top margin in inches, can be negative. - ``width``. Width in pixels. - ``wrappingStyle``. Wrapping style, *inline*, *square*, *tight*, *behind*, or *infront*. +- ``wrapDistanceTop``. Top text wrapping in pixels. +- ``wrapDistanceBottom``. Bottom text wrapping in pixels. +- ``wrapDistanceLeft``. Left text wrapping in pixels. +- ``wrapDistanceRight``. Right text wrapping in pixels. .. _numbering-level-style: diff --git a/tests/PhpWord/Writer/HTML/ElementTest.php b/tests/PhpWord/Writer/HTML/ElementTest.php index ceb3abcbdb..b99a5c9a19 100644 --- a/tests/PhpWord/Writer/HTML/ElementTest.php +++ b/tests/PhpWord/Writer/HTML/ElementTest.php @@ -17,9 +17,9 @@ namespace PhpOffice\PhpWord\Writer\HTML; -use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Element\Text as TextElement; use PhpOffice\PhpWord\Element\TrackChange; +use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Writer\HTML; use PhpOffice\PhpWord\Writer\HTML\Element\Text; From bb70eb0b4c37fa059d53c9714da88150f1ed3cfc Mon Sep 17 00:00:00 2001 From: troosan Date: Sun, 18 Mar 2018 12:37:39 +0100 Subject: [PATCH 057/135] fix docx parsing --- src/PhpWord/Reader/Word2007/AbstractPart.php | 143 +++++++++--------- src/PhpWord/Writer/HTML/Element/Title.php | 14 +- src/PhpWord/Writer/ODText/Element/Title.php | 8 +- src/PhpWord/Writer/RTF/Element/Text.php | 2 +- tests/PhpWord/Reader/Word2007/ElementTest.php | 91 ++++++++++- tests/PhpWord/Reader/Word2007/StyleTest.php | 9 +- tests/PhpWord/Writer/Word2007Test.php | 2 +- 7 files changed, 180 insertions(+), 89 deletions(-) diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 9d00262363..7509a382c5 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -18,6 +18,7 @@ namespace PhpOffice\PhpWord\Reader\Word2007; use PhpOffice\Common\XMLReader; +use PhpOffice\PhpWord\Element\AbstractContainer; use PhpOffice\PhpWord\Element\TextRun; use PhpOffice\PhpWord\Element\TrackChange; use PhpOffice\PhpWord\PhpWord; @@ -161,20 +162,14 @@ protected function readParagraph(XMLReader $xmlReader, \DOMElement $domNode, $pa $parent->addTitle($textContent, $headingDepth); } else { // Text and TextRun - $runCount = $xmlReader->countElements('w:r', $domNode); - $insCount = $xmlReader->countElements('w:ins', $domNode); - $delCount = $xmlReader->countElements('w:del', $domNode); - $linkCount = $xmlReader->countElements('w:hyperlink', $domNode); - $runLinkCount = $runCount + $insCount + $delCount + $linkCount; - if (0 == $runLinkCount) { + $textRunContainers = $xmlReader->countElements('w:r|w:ins|w:del|w:hyperlink|w:smartTag', $domNode); + if (0 === $textRunContainers) { $parent->addTextBreak(null, $paragraphStyle); } else { $nodes = $xmlReader->getElements('*', $domNode); - if ($runLinkCount > 1) { - $parent = $parent->addTextRun($paragraphStyle); - } + $paragraph = $parent->addTextRun($paragraphStyle); foreach ($nodes as $node) { - $this->readRun($xmlReader, $node, $parent, $docPart, $paragraphStyle); + $this->readRun($xmlReader, $node, $paragraph, $docPart, $paragraphStyle); } } } @@ -216,81 +211,85 @@ private function getHeadingDepth(array $paragraphStyle = null) */ protected function readRun(XMLReader $xmlReader, \DOMElement $domNode, $parent, $docPart, $paragraphStyle = null) { - if (in_array($domNode->nodeName, array('w:ins', 'w:del'))) { + if (in_array($domNode->nodeName, array('w:ins', 'w:del', 'w:smartTag', 'w:hyperlink'))) { $nodes = $xmlReader->getElements('*', $domNode); foreach ($nodes as $node) { - return $this->readRun($xmlReader, $node, $parent, $docPart, $paragraphStyle); + $this->readRun($xmlReader, $node, $parent, $docPart, $paragraphStyle); + } + } elseif ($domNode->nodeName == 'w:r') { + $fontStyle = $this->readFontStyle($xmlReader, $domNode); + $nodes = $xmlReader->getElements('*', $domNode); + foreach ($nodes as $node) { + $this->readRunChild($xmlReader, $node, $parent, $docPart, $paragraphStyle, $fontStyle); } } + } - if (!in_array($domNode->nodeName, array('w:r', 'w:hyperlink'))) { - return; - } - $fontStyle = $this->readFontStyle($xmlReader, $domNode); - - // Link - if ('w:hyperlink' == $domNode->nodeName) { - $rId = $xmlReader->getAttribute('r:id', $domNode); - $textContent = $xmlReader->getValue('w:r/w:t', $domNode); + /** + * Parses nodes under w:r + * + * @param XMLReader $xmlReader + * @param \DOMElement $node + * @param AbstractContainer $parent + * @param string $docPart + * @param mixed $paragraphStyle + * @param mixed $fontStyle + */ + protected function readRunChild(XMLReader $xmlReader, \DOMElement $node, AbstractContainer $parent, $docPart, $paragraphStyle = null, $fontStyle = null) + { + $runParent = $node->parentNode->parentNode; + if ($node->nodeName == 'w:footnoteReference') { + // Footnote + $wId = $xmlReader->getAttribute('w:id', $node); + $footnote = $parent->addFootnote(); + $footnote->setRelationId($wId); + } elseif ($node->nodeName == 'w:endnoteReference') { + // Endnote + $wId = $xmlReader->getAttribute('w:id', $node); + $endnote = $parent->addEndnote(); + $endnote->setRelationId($wId); + } elseif ($node->nodeName == 'w:pict') { + // Image + $rId = $xmlReader->getAttribute('r:id', $node, 'v:shape/v:imagedata'); $target = $this->getMediaTarget($docPart, $rId); if (!is_null($target)) { - $parent->addLink($target, $textContent, $fontStyle, $paragraphStyle); - } - } else { - if ($xmlReader->elementExists('w:footnoteReference', $domNode)) { - // Footnote - $wId = $xmlReader->getAttribute('w:id', $domNode, 'w:footnoteReference'); - $footnote = $parent->addFootnote(); - $footnote->setRelationId($wId); - } elseif ($xmlReader->elementExists('w:endnoteReference', $domNode)) { - // Endnote - $wId = $xmlReader->getAttribute('w:id', $domNode, 'w:endnoteReference'); - $endnote = $parent->addEndnote(); - $endnote->setRelationId($wId); - } elseif ($xmlReader->elementExists('w:pict', $domNode)) { - // Image - $rId = $xmlReader->getAttribute('r:id', $domNode, 'w:pict/v:shape/v:imagedata'); - $target = $this->getMediaTarget($docPart, $rId); - if (!is_null($target)) { - if ('External' == $this->getTargetMode($docPart, $rId)) { - $imageSource = $target; - } else { - $imageSource = "zip://{$this->docFile}#{$target}"; - } - $parent->addImage($imageSource); - } - } elseif ($xmlReader->elementExists('w:object', $domNode)) { - // Object - $rId = $xmlReader->getAttribute('r:id', $domNode, 'w:object/o:OLEObject'); - // $rIdIcon = $xmlReader->getAttribute('r:id', $domNode, 'w:object/v:shape/v:imagedata'); - $target = $this->getMediaTarget($docPart, $rId); - if (!is_null($target)) { - $textContent = "<Object: {$target}>"; - $parent->addText($textContent, $fontStyle, $paragraphStyle); + if ('External' == $this->getTargetMode($docPart, $rId)) { + $imageSource = $target; + } else { + $imageSource = "zip://{$this->docFile}#{$target}"; } + $parent->addImage($imageSource); } - if ($xmlReader->elementExists('w:br', $domNode)) { - $parent->addTextBreak(); + } elseif ($node->nodeName == 'w:object') { + // Object + $rId = $xmlReader->getAttribute('r:id', $node, 'o:OLEObject'); + // $rIdIcon = $xmlReader->getAttribute('r:id', $domNode, 'w:object/v:shape/v:imagedata'); + $target = $this->getMediaTarget($docPart, $rId); + if (!is_null($target)) { + $textContent = "<Object: {$target}>"; + $parent->addText($textContent, $fontStyle, $paragraphStyle); } - if ($xmlReader->elementExists('w:t', $domNode) || $xmlReader->elementExists('w:tab', $domNode) || $xmlReader->elementExists('w:delText', $domNode)) { - // TextRun - $textContent = ''; - $nodes = $xmlReader->getElements('w:t|w:delText|w:tab', $domNode); - foreach ($nodes as $node) { - if ($node->nodeName == 'w:t') { - $textContent .= $node->nodeValue; - } elseif ($node->nodeName == 'w:delText') { - $textContent .= $node->nodeValue; - } elseif ($node->nodeName == 'w:tab') { - $textContent .= "\t"; - } + } elseif ($node->nodeName == 'w:br') { + $parent->addTextBreak(); + } elseif ($node->nodeName == 'w:tab') { + $parent->addText("\t"); + } elseif ($node->nodeName == 'w:t' || $node->nodeName == 'w:delText') { + // TextRun + $textContent = $xmlReader->getValue('.', $node); + + if ($runParent->nodeName == 'w:hyperlink') { + $rId = $xmlReader->getAttribute('r:id', $runParent); + $target = $this->getMediaTarget($docPart, $rId); + if (!is_null($target)) { + $parent->addLink($target, $textContent, $fontStyle, $paragraphStyle); } + } else { /** @var AbstractElement $element */ $element = $parent->addText($textContent, $fontStyle, $paragraphStyle); - if (in_array($domNode->parentNode->nodeName, array('w:ins', 'w:del'))) { - $type = ($domNode->parentNode->nodeName == 'w:del') ? TrackChange::DELETED : TrackChange::INSERTED; - $author = $domNode->parentNode->getAttribute('w:author'); - $date = \DateTime::createFromFormat('Y-m-d\TH:i:s\Z', $domNode->parentNode->getAttribute('w:date')); + if (in_array($runParent->nodeName, array('w:ins', 'w:del'))) { + $type = ($runParent->nodeName == 'w:del') ? TrackChange::DELETED : TrackChange::INSERTED; + $author = $runParent->getAttribute('w:author'); + $date = \DateTime::createFromFormat('Y-m-d\TH:i:s\Z', $runParent->getAttribute('w:date')); $element->setChangeInfo($type, $author, $date); } } diff --git a/src/PhpWord/Writer/HTML/Element/Title.php b/src/PhpWord/Writer/HTML/Element/Title.php index 3a80201848..7307ce0c17 100644 --- a/src/PhpWord/Writer/HTML/Element/Title.php +++ b/src/PhpWord/Writer/HTML/Element/Title.php @@ -38,11 +38,17 @@ public function write() } $tag = 'h' . $this->element->getDepth(); - if (Settings::isOutputEscapingEnabled()) { - $text = $this->escaper->escapeHtml($this->element->getText()); - } else { - $text = $this->element->getText(); + + $text = $this->element->getText(); + if (is_string($text)) { + if (Settings::isOutputEscapingEnabled()) { + $text = $this->escaper->escapeHtml($text); + } + } elseif ($text instanceof \PhpOffice\PhpWord\Element\AbstractContainer) { + $writer = new Container($this->parentWriter, $this->element); + $text = $writer->write(); } + $content = "<{$tag}>{$text}" . PHP_EOL; return $content; diff --git a/src/PhpWord/Writer/ODText/Element/Title.php b/src/PhpWord/Writer/ODText/Element/Title.php index 343949a2f1..8b9440ab8c 100644 --- a/src/PhpWord/Writer/ODText/Element/Title.php +++ b/src/PhpWord/Writer/ODText/Element/Title.php @@ -37,7 +37,13 @@ public function write() $xmlWriter->startElement('text:h'); $xmlWriter->writeAttribute('text:outline-level', $element->getDepth()); - $this->writeText($element->getText()); + $text = $element->getText(); + if (is_string($text)) { + $this->writeText($text); + } elseif ($text instanceof \PhpOffice\PhpWord\Element\AbstractContainer) { + $containerWriter = new Container($xmlWriter, $text); + $containerWriter->write(); + } $xmlWriter->endElement(); // text:h } } diff --git a/src/PhpWord/Writer/RTF/Element/Text.php b/src/PhpWord/Writer/RTF/Element/Text.php index f80e793534..b9e56e890b 100644 --- a/src/PhpWord/Writer/RTF/Element/Text.php +++ b/src/PhpWord/Writer/RTF/Element/Text.php @@ -34,7 +34,7 @@ public function write() /** @var \PhpOffice\PhpWord\Element\Text $element Type hint */ $element = $this->element; $elementClass = str_replace('\\Writer\\RTF', '', get_class($this)); - if (!$element instanceof $elementClass) { + if (!$element instanceof $elementClass || !is_string($element->getText())) { return ''; } diff --git a/tests/PhpWord/Reader/Word2007/ElementTest.php b/tests/PhpWord/Reader/Word2007/ElementTest.php index 4678027828..75060625fd 100644 --- a/tests/PhpWord/Reader/Word2007/ElementTest.php +++ b/tests/PhpWord/Reader/Word2007/ElementTest.php @@ -18,6 +18,7 @@ namespace PhpOffice\PhpWord\Reader\Word2007; use PhpOffice\PhpWord\AbstractTestReader; +use PhpOffice\PhpWord\Element\TrackChange; /** * Test class for PhpOffice\PhpWord\Reader\Word2007\Element subnamespace @@ -39,9 +40,35 @@ public function testReadTextBreak() $phpWord = $this->getDocumentFromString(array('document' => $documentXml)); $elements = $phpWord->getSection(0)->getElements(); - $this->assertInstanceOf('PhpOffice\PhpWord\Element\TextBreak', $elements[0]); - $this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $elements[1]); - $this->assertEquals('test string', $elements[1]->getText()); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $elements[0]); + /** @var \PhpOffice\PhpWord\Element\TextRun $textRun */ + $textRun = $elements[0]; + $this->assertInstanceOf('PhpOffice\PhpWord\Element\TextBreak', $textRun->getElement(0)); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $textRun->getElement(1)); + $this->assertEquals('test string', $textRun->getElement(1)->getText()); + } + + /** + * Test reading content inside w:smartTag + */ + public function testSmartTag() + { + $documentXml = ' + + + test string + + + '; + + $phpWord = $this->getDocumentFromString(array('document' => $documentXml)); + + $elements = $phpWord->getSection(0)->getElements(); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $elements[0]); + /** @var \PhpOffice\PhpWord\Element\TextRun $textRun */ + $textRun = $elements[0]; + $this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $textRun->getElement(0)); + $this->assertEquals('test string', $textRun->getElement(0)->getText()); } /** @@ -85,6 +112,49 @@ public function testReadListItemRunWithFormatting() $this->assertTrue($listElements[2]->getFontStyle()->getBold()); } + /** + * Test reading track changes + */ + public function testReadTrackChange() + { + $documentXml = ' + + One + + + + two + + + + + three + + + '; + + $phpWord = $this->getDocumentFromString(array('document' => $documentXml)); + + $elements = $phpWord->getSection(0)->getElements(); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $elements[0]); + /** @var \PhpOffice\PhpWord\Element\TextRun $elements */ + $textRun = $elements[0]; + + $this->assertEquals('One ', $textRun->getElement(0)->getText()); + + $this->assertEquals('two', $textRun->getElement(1)->getText()); + $this->assertNotNull($textRun->getElement(1)->getTrackChange()); + /** @var \PhpOffice\PhpWord\Element\TrackChange $trackChange */ + $trackChange = $textRun->getElement(1)->getTrackChange(); + $this->assertEquals(TrackChange::DELETED, $trackChange->getChangeType()); + + $this->assertEquals('three', $textRun->getElement(2)->getText()); + $this->assertNotNull($textRun->getElement(2)->getTrackChange()); + /** @var \PhpOffice\PhpWord\Element\TrackChange $trackChange */ + $trackChange = $textRun->getElement(2)->getTrackChange(); + $this->assertEquals(TrackChange::INSERTED, $trackChange->getChangeType()); + } + /** * Test reading of tab */ @@ -98,11 +168,18 @@ public function testReadTab() '; - $phpWord = $this->getDocumentFromString($documentXml); + $phpWord = $this->getDocumentFromString(array('document' => $documentXml)); - $elements = $this->get($phpWord->getSections(), 0)->getElements(); - $this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $elements[0]); - $this->assertEquals("One\tTwo", $elements[0]->getText()); + $elements = $phpWord->getSection(0)->getElements(); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $elements[0]); + /** @var \PhpOffice\PhpWord\Element\TextRun $textRun */ + $textRun = $elements[0]; + $this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $textRun->getElement(0)); + $this->assertEquals('One', $textRun->getElement(0)->getText()); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $textRun->getElement(1)); + $this->assertEquals("\t", $textRun->getElement(1)->getText()); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $textRun->getElement(2)); + $this->assertEquals('Two', $textRun->getElement(2)->getText()); } /** diff --git a/tests/PhpWord/Reader/Word2007/StyleTest.php b/tests/PhpWord/Reader/Word2007/StyleTest.php index 46421d97a7..9bb6d3bdbd 100644 --- a/tests/PhpWord/Reader/Word2007/StyleTest.php +++ b/tests/PhpWord/Reader/Word2007/StyleTest.php @@ -117,10 +117,13 @@ public function testReadPosition() $phpWord = $this->getDocumentFromString(array('document' => $documentXml)); $elements = $phpWord->getSection(0)->getElements(); - $this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $elements[0]); - $this->assertInstanceOf('PhpOffice\PhpWord\Style\Font', $elements[0]->getFontStyle()); + /** @var \PhpOffice\PhpWord\Element\TextRun $elements */ + $textRun = $elements[0]; + $this->assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $textRun); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\Text', $textRun->getElement(0)); + $this->assertInstanceOf('PhpOffice\PhpWord\Style\Font', $textRun->getElement(0)->getFontStyle()); /** @var \PhpOffice\PhpWord\Style\Font $fontStyle */ - $fontStyle = $elements[0]->getFontStyle(); + $fontStyle = $textRun->getElement(0)->getFontStyle(); $this->assertEquals(15, $fontStyle->getPosition()); } } diff --git a/tests/PhpWord/Writer/Word2007Test.php b/tests/PhpWord/Writer/Word2007Test.php index 22a0e6dfdb..0db36fc19a 100644 --- a/tests/PhpWord/Writer/Word2007Test.php +++ b/tests/PhpWord/Writer/Word2007Test.php @@ -75,7 +75,7 @@ public function testConstruct() public function testSave() { $localImage = __DIR__ . '/../_files/images/earth.jpg'; - $remoteImage = 'http://php.net//images/logos/php-med-trans-light.gif'; + $remoteImage = 'http://php.net/images/logos/new-php-logo.png'; $phpWord = new PhpWord(); $phpWord->addFontStyle('Font', array('size' => 11)); $phpWord->addParagraphStyle('Paragraph', array('alignment' => Jc::CENTER)); From 4c846426ce68998d6846660338093a535a784f33 Mon Sep 17 00:00:00 2001 From: troosan Date: Sun, 18 Mar 2018 20:53:05 +0100 Subject: [PATCH 058/135] format & changelog --- CHANGELOG.md | 1 + src/PhpWord/Element/Field.php | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4515131ec..b58ec404c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ v0.15.0 (?? ??? 2018) - Bookmark are not writton as internal link in html writer @troosan #1263 - It should be possible to add a Footnote in a ListItemRun @troosan #1287 #1287 - Fix parsing of Heading and Title formating @troosan @gthomas2 #465 +- Fix Dateformat typo, fix hours casing, add Month-Day-Year formats @ComputerTinker #591 ### Changed - Remove zend-stdlib dependency @Trainmaster #1284 diff --git a/src/PhpWord/Element/Field.php b/src/PhpWord/Element/Field.php index e5377cf41c..0e5e28ed6d 100644 --- a/src/PhpWord/Element/Field.php +++ b/src/PhpWord/Element/Field.php @@ -46,8 +46,8 @@ class Field extends AbstractElement ), 'options' => array('PreserveFormat'), ), - 'DATE'=>array( - 'properties'=> array( + 'DATE' => array( + 'properties' => array( 'dateformat' => array( /* Generic formats */ 'yyyy-MM-dd', 'yyyy-MM', 'MMM-yy', 'MMM-yyyy', 'h:mm am/pm', 'h:mm:ss am/pm', 'HH:mm', 'HH:mm:ss', From 997e21433ccb397ac8a547863227e33f75089eb1 Mon Sep 17 00:00:00 2001 From: troosan Date: Sun, 18 Mar 2018 22:26:45 +0100 Subject: [PATCH 059/135] add parsing of line-height and text-indent --- src/PhpWord/Shared/Html.php | 6 ++++++ tests/PhpWord/Shared/HtmlTest.php | 28 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 15f3b605c1..64c6b4a5ce 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -520,6 +520,12 @@ private static function parseStyle($attribute, $styles) case 'background-color': $styles['bgColor'] = trim($cValue, '#'); break; + case 'line-height': + $styles['lineHeight'] = $cValue; + break; + case 'text-indent': + $styles['indentation']['firstLine'] = Converter::cssToTwip($cValue); + break; case 'font-weight': $tValue = false; if (preg_match('#bold#', $cValue)) { diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index 7541c9c460..eda7abb81e 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -114,6 +114,34 @@ public function testParseTextDecoration() $this->assertEquals('single', $doc->getElementAttribute('/w:document/w:body/w:p/w:r/w:rPr/w:u', 'w:val')); } + /** + * Test line-height style + */ + public function testParseLineHeight() + { + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + Html::addHtml($section, '

        test

        '); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:pPr/w:spacing')); + $this->assertEquals(240 * 1.5, $doc->getElementAttribute('/w:document/w:body/w:p/w:pPr/w:spacing', 'w:line')); + } + + /** + * Test text-indent style + */ + public function testParseTextIndent() + { + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + Html::addHtml($section, '

        test

        '); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:pPr/w:ind')); + $this->assertEquals(750, $doc->getElementAttribute('/w:document/w:body/w:p/w:pPr/w:ind', 'w:firstLine')); + } + /** * Test text-align style */ From de2e05bc112887332ea8800e5ddee255d1f83639 Mon Sep 17 00:00:00 2001 From: troosan Date: Mon, 19 Mar 2018 06:41:46 +0100 Subject: [PATCH 060/135] update changelog [ci skip] --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b58ec404c5..e2bf4eb729 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ v0.15.0 (?? ??? 2018) - Add support for Hyphenation @Trainmaster #1282 (Document: `autoHyphenation`, `consecutiveHyphenLimit`, `hyphenationZone`, `doNotHyphenateCaps`, Paragraph: `suppressAutoHyphens`) - Added support for Floating Table Positioning (tblpPr) @anrikun #639 - Added support for Image text wrapping distance @troosan #1310 +- Added parsing of CSS line-height and text-indent in HTML reader @troosan #1316 ### Fixed - Fix reading of docx default style - @troosan #1238 From 97d60dd985363681bfd376aacee776898032ea3d Mon Sep 17 00:00:00 2001 From: troosan Date: Mon, 19 Mar 2018 17:25:19 +0100 Subject: [PATCH 061/135] tranlate percentage to rate --- samples/Sample_26_Html.php | 3 +++ src/PhpWord/Shared/Html.php | 11 ++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/samples/Sample_26_Html.php b/samples/Sample_26_Html.php index 31e5984f71..d876380531 100644 --- a/samples/Sample_26_Html.php +++ b/samples/Sample_26_Html.php @@ -18,6 +18,9 @@ $html .= '

        Unordered (bulleted) list:

        '; $html .= '
        • Item 1
        • Item 2
          • Item 2.1
          • Item 2.1
        '; +$html .= '

        1.5 line height with first line text indent:

        '; +$html .= '

        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

        '; + $html .= '

        centered title

        '; $html .= '

        Ordered (numbered) list:

        '; diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 64c6b4a5ce..dcf847787d 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -521,7 +521,7 @@ private static function parseStyle($attribute, $styles) $styles['bgColor'] = trim($cValue, '#'); break; case 'line-height': - $styles['lineHeight'] = $cValue; + $styles['lineHeight'] = Html::toMultiplier($cValue); break; case 'text-indent': $styles['indentation']['firstLine'] = Converter::cssToTwip($cValue); @@ -681,6 +681,15 @@ private static function mapAlign($cssAlignment) return null; } + private static function toMultiplier($cssValue) + { + if (preg_match('/([0-9]+)%/', $cssValue, $matches)) { + return ((int) $matches[1]) / 100; + } + + return $cssValue; + } + /** * Parse line break * From de01e86d41e397891fe5a8255b2b595ccd883b75 Mon Sep 17 00:00:00 2001 From: troosan Date: Mon, 19 Mar 2018 22:43:10 +0100 Subject: [PATCH 062/135] parse fixed line space --- src/PhpWord/Shared/Html.php | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index dcf847787d..f8b256057f 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -521,7 +521,18 @@ private static function parseStyle($attribute, $styles) $styles['bgColor'] = trim($cValue, '#'); break; case 'line-height': - $styles['lineHeight'] = Html::toMultiplier($cValue); + if (preg_match('/([0-9]+[a-z]+)/', $cValue, $matches)) { + $spacingLineRule = \PhpOffice\PhpWord\SimpleType\LineSpacingRule::EXACT; + $spacing = Converter::cssToTwip($matches[1]) / \PhpOffice\PhpWord\Style\Paragraph::LINE_HEIGHT; + } elseif (preg_match('/([0-9]+)%/', $cValue, $matches)) { + $spacingLineRule = \PhpOffice\PhpWord\SimpleType\LineSpacingRule::AUTO; + $spacing = ((int) $matches[1]) / 100; + } else { + $spacingLineRule = \PhpOffice\PhpWord\SimpleType\LineSpacingRule::AUTO; + $spacing = $cValue; + } + $styles['spacingLineRule'] = $spacingLineRule; + $styles['lineHeight'] = $spacing; break; case 'text-indent': $styles['indentation']['firstLine'] = Converter::cssToTwip($cValue); @@ -681,15 +692,6 @@ private static function mapAlign($cssAlignment) return null; } - private static function toMultiplier($cssValue) - { - if (preg_match('/([0-9]+)%/', $cssValue, $matches)) { - return ((int) $matches[1]) / 100; - } - - return $cssValue; - } - /** * Parse line break * From 16a9ded2c97304c89d0a7f1c4f34aa72c12e3818 Mon Sep 17 00:00:00 2001 From: troosan Date: Mon, 19 Mar 2018 22:49:00 +0100 Subject: [PATCH 063/135] add exact line spacing test --- tests/PhpWord/Shared/HtmlTest.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index eda7abb81e..386aaee121 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -20,6 +20,8 @@ use PhpOffice\PhpWord\Element\Section; use PhpOffice\PhpWord\SimpleType\Jc; use PhpOffice\PhpWord\TestHelperDOCX; +use PhpOffice\PhpWord\Style\Paragraph; +use PhpOffice\PhpWord\SimpleType\LineSpacingRule; /** * Test class for PhpOffice\PhpWord\Shared\Html @@ -122,10 +124,16 @@ public function testParseLineHeight() $phpWord = new \PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); Html::addHtml($section, '

        test

        '); + Html::addHtml($section, '

        test

        '); $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); - $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:pPr/w:spacing')); - $this->assertEquals(240 * 1.5, $doc->getElementAttribute('/w:document/w:body/w:p/w:pPr/w:spacing', 'w:line')); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:pPr/w:spacing')); + $this->assertEquals(Paragraph::LINE_HEIGHT * 1.5, $doc->getElementAttribute('/w:document/w:body/w:p[1]/w:pPr/w:spacing', 'w:line')); + $this->assertEquals(LineSpacingRule::AUTO, $doc->getElementAttribute('/w:document/w:body/w:p[1]/w:pPr/w:spacing', 'w:lineRule')); + + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p[2]/w:pPr/w:spacing')); + $this->assertEquals(300, $doc->getElementAttribute('/w:document/w:body/w:p[2]/w:pPr/w:spacing', 'w:line')); + $this->assertEquals(LineSpacingRule::EXACT, $doc->getElementAttribute('/w:document/w:body/w:p[2]/w:pPr/w:spacing', 'w:lineRule')); } /** From f73beaa26a90ece5eab8015b2127347fd35076f2 Mon Sep 17 00:00:00 2001 From: troosan Date: Mon, 19 Mar 2018 23:06:00 +0100 Subject: [PATCH 064/135] reset static collections at instantiation --- src/PhpWord/PhpWord.php | 13 +++++++++++++ tests/PhpWord/Shared/HtmlTest.php | 4 ++-- tests/PhpWord/Style/TablePositionTest.php | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/PhpWord/PhpWord.php b/src/PhpWord/PhpWord.php index 6b6fd9ffe8..d524adc7b4 100644 --- a/src/PhpWord/PhpWord.php +++ b/src/PhpWord/PhpWord.php @@ -52,8 +52,17 @@ class PhpWord * @const string|int */ const DEFAULT_FONT_NAME = Settings::DEFAULT_FONT_NAME; + /** + * @deprecated 0.11.0 Use Settings constants + */ const DEFAULT_FONT_SIZE = Settings::DEFAULT_FONT_SIZE; + /** + * @deprecated 0.11.0 Use Settings constants + */ const DEFAULT_FONT_COLOR = Settings::DEFAULT_FONT_COLOR; + /** + * @deprecated 0.11.0 Use Settings constants + */ const DEFAULT_FONT_CONTENT_TYPE = Settings::DEFAULT_FONT_CONTENT_TYPE; /** @@ -85,6 +94,10 @@ class PhpWord */ public function __construct() { + // Reset Media and styles + Media::resetStyles(); + Style::resetStyles(); + // Collection $collections = array('Bookmarks', 'Titles', 'Footnotes', 'Endnotes', 'Charts', 'Comments'); foreach ($collections as $collection) { diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index 386aaee121..1171489c96 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -19,9 +19,9 @@ use PhpOffice\PhpWord\Element\Section; use PhpOffice\PhpWord\SimpleType\Jc; -use PhpOffice\PhpWord\TestHelperDOCX; -use PhpOffice\PhpWord\Style\Paragraph; use PhpOffice\PhpWord\SimpleType\LineSpacingRule; +use PhpOffice\PhpWord\Style\Paragraph; +use PhpOffice\PhpWord\TestHelperDOCX; /** * Test class for PhpOffice\PhpWord\Shared\Html diff --git a/tests/PhpWord/Style/TablePositionTest.php b/tests/PhpWord/Style/TablePositionTest.php index 77b22e4e14..1243c3d595 100644 --- a/tests/PhpWord/Style/TablePositionTest.php +++ b/tests/PhpWord/Style/TablePositionTest.php @@ -11,7 +11,7 @@ * contributors, visit https://github.com/PHPOffice/PHPWord/contributors. * * @see https://github.com/PHPOffice/PHPWord - * @copyright 2010-2017 PHPWord contributors + * @copyright 2010-2018 PHPWord contributors * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ From 992d8425521cb15f8b3a440a973a3b4394da1435 Mon Sep 17 00:00:00 2001 From: troosan Date: Mon, 19 Mar 2018 23:07:35 +0100 Subject: [PATCH 065/135] fix --- src/PhpWord/PhpWord.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/PhpWord.php b/src/PhpWord/PhpWord.php index d524adc7b4..b5cc0c5151 100644 --- a/src/PhpWord/PhpWord.php +++ b/src/PhpWord/PhpWord.php @@ -95,7 +95,7 @@ class PhpWord public function __construct() { // Reset Media and styles - Media::resetStyles(); + Media::resetElements(); Style::resetStyles(); // Collection From 296706aa03ad9c24b35528acdb052feb0219ee96 Mon Sep 17 00:00:00 2001 From: troosan Date: Tue, 20 Mar 2018 21:35:06 +0100 Subject: [PATCH 066/135] add unit tests --- CHANGELOG.md | 1 + samples/Sample_09_Tables.php | 22 ++++---- tests/PhpWord/Writer/HTML/ElementTest.php | 68 +++++++++++++++++++++++ 3 files changed, 80 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6f87158a6..526b9c95dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ v0.15.0 (?? ??? 2018) - Fix parsing of `` tag. @troosan #1274 - Bookmark are not writton as internal link in html writer @troosan #1263 - It should be possible to add a Footnote in a ListItemRun @troosan #1287 #1287 +- Fix colspan and rowspan for tables in HTML Writer @mattbolt #1292 ### Changed - Remove zend-stdlib dependency @Trainmaster #1284 diff --git a/samples/Sample_09_Tables.php b/samples/Sample_09_Tables.php index ba41aa5484..b1231d55cf 100644 --- a/samples/Sample_09_Tables.php +++ b/samples/Sample_09_Tables.php @@ -113,20 +113,20 @@ $table = $section->addTable('Colspan Rowspan'); $row = $table->addRow(); - -$row->addCell(null, array('vMerge' => 'restart'))->addText('A'); -$row->addCell(null, array('gridSpan' => 2, 'vMerge' => 'restart'))->addText('B'); -$row->addCell()->addText('1'); +$row->addCell(1000, array('vMerge' => 'restart'))->addText('A'); +$row->addCell(1000, array('gridSpan' => 2, 'vMerge' => 'restart'))->addText('B'); +$row->addCell(1000)->addText('1'); $row = $table->addRow(); -$row->addCell(null, array('vMerge' => 'continue')); -$row->addCell(null, array('vMerge' => 'continue', 'gridSpan' => 2)); -$row->addCell()->addText('2'); +$row->addCell(1000, array('vMerge' => 'continue')); +$row->addCell(1000, array('vMerge' => 'continue', 'gridSpan' => 2)); +$row->addCell(1000)->addText('2'); + $row = $table->addRow(); -$row->addCell(null, array('vMerge' => 'continue')); -$row->addCell()->addText('C'); -$row->addCell()->addText('D'); -$row->addCell()->addText('3'); +$row->addCell(1000, array('vMerge' => 'continue')); +$row->addCell(1000)->addText('C'); +$row->addCell(1000)->addText('D'); +$row->addCell(1000)->addText('3'); // 5. Nested table diff --git a/tests/PhpWord/Writer/HTML/ElementTest.php b/tests/PhpWord/Writer/HTML/ElementTest.php index fc092ba313..eb0d257121 100644 --- a/tests/PhpWord/Writer/HTML/ElementTest.php +++ b/tests/PhpWord/Writer/HTML/ElementTest.php @@ -18,6 +18,7 @@ namespace PhpOffice\PhpWord\Writer\HTML; use PhpOffice\PhpWord\Element\Text as TextElement; +use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Writer\HTML; use PhpOffice\PhpWord\Writer\HTML\Element\Text; @@ -54,4 +55,71 @@ public function testWriteTextElement() $this->assertEquals(htmlspecialchars('-A-', ENT_COMPAT, 'UTF-8'), $object->write()); } + + /** + * Tests writing table with col span + */ + public function testWriteColSpan() + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $table = $section->addTable(); + $row1 = $table->addRow(); + $cell11 = $row1->addCell(1000, array('gridSpan' => 2)); + $cell11->addText('cell spanning 2 bellow'); + $row2 = $table->addRow(); + $cell21 = $row2->addCell(500); + $cell21->addText('first cell'); + $cell22 = $row2->addCell(500); + $cell22->addText('second cell'); + + $dom = $this->getAsHTML($phpWord); + echo $dom->saveHTML(); + + $xpath = new \DOMXpath($dom); + + $this->assertTrue($xpath->query('/html/body/table/tr[1]/td')->length == 1); + $this->assertEquals('2', $xpath->query('/html/body/table/tr/td[1]')->item(0)->attributes->getNamedItem('colspan')->textContent); + $this->assertTrue($xpath->query('/html/body/table/tr[2]/td')->length == 2); + } + + /** + * Tests writing table with row span + */ + public function testWriteRowSpan() + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + $table = $section->addTable(); + + $row1 = $table->addRow(); + $row1->addCell(1000, array('vMerge' => 'restart'))->addText('row spanning 3 bellow'); + $row1->addCell(500)->addText('first cell being spanned'); + + $row2 = $table->addRow(); + $row2->addCell(null, array('vMerge' => 'continue')); + $row2->addCell(500)->addText('second cell being spanned'); + + $row3 = $table->addRow(); + $row3->addCell(null, array('vMerge' => 'continue')); + $row3->addCell(500)->addText('third cell being spanned'); + + $dom = $this->getAsHTML($phpWord); + echo $dom->saveHTML(); + + $xpath = new \DOMXpath($dom); + + $this->assertTrue($xpath->query('/html/body/table/tr[1]/td')->length == 2); + $this->assertEquals('3', $xpath->query('/html/body/table/tr[1]/td[1]')->item(0)->attributes->getNamedItem('rowspan')->textContent); + $this->assertTrue($xpath->query('/html/body/table/tr[2]/td')->length == 1); + } + + private function getAsHTML(PhpWord $phpWord) + { + $htmlWriter = new HTML($phpWord); + $dom = new \DOMDocument(); + $dom->loadHTML($htmlWriter->getContent()); + + return $dom; + } } From d8387c1abad2e0e44af3f936cad0e6d5746ad271 Mon Sep 17 00:00:00 2001 From: Tim Jarrett Date: Tue, 2 Feb 2016 16:17:20 -0500 Subject: [PATCH 067/135] Escape incoming invalid XML characters using htmlspecialchars(). --- src/PhpWord/Reader/Word2007/AbstractPart.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 7509a382c5..9623fb795a 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -135,7 +135,7 @@ protected function readParagraph(XMLReader $xmlReader, \DOMElement $domNode, $pa } } } - $parent->addPreserveText($textContent, $fontStyle, $paragraphStyle); + $parent->addPreserveText(htmlspecialchars($textContent, ENT_QUOTES | ENT_XML1), $fontStyle, $paragraphStyle); } elseif ($xmlReader->elementExists('w:pPr/w:numPr', $domNode)) { // List item $numId = $xmlReader->getAttribute('w:val', $domNode, 'w:pPr/w:numPr/w:numId'); @@ -152,7 +152,7 @@ protected function readParagraph(XMLReader $xmlReader, \DOMElement $domNode, $pa $textContent = null; $nodes = $xmlReader->getElements('w:r', $domNode); if ($nodes->length === 1) { - $textContent = $xmlReader->getValue('w:t', $nodes->item(0)); + $textContent = htmlspecialchars($xmlReader->getValue('w:t', $nodes->item(0)), ENT_QUOTES | ENT_XML1); } else { $textContent = new TextRun($paragraphStyle); foreach ($nodes as $node) { @@ -275,7 +275,7 @@ protected function readRunChild(XMLReader $xmlReader, \DOMElement $node, Abstrac $parent->addText("\t"); } elseif ($node->nodeName == 'w:t' || $node->nodeName == 'w:delText') { // TextRun - $textContent = $xmlReader->getValue('.', $node); + $textContent = htmlspecialchars($xmlReader->getValue('.', $node), ENT_QUOTES | ENT_XML1); if ($runParent->nodeName == 'w:hyperlink') { $rId = $xmlReader->getAttribute('r:id', $runParent); From 2c5970a38880d66ffb4db6870825f581755b44ee Mon Sep 17 00:00:00 2001 From: troosan Date: Tue, 20 Mar 2018 23:42:01 +0100 Subject: [PATCH 068/135] php 5.3 compatibility --- src/PhpWord/Reader/Word2007/AbstractPart.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 9623fb795a..f64886cfda 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -135,7 +135,7 @@ protected function readParagraph(XMLReader $xmlReader, \DOMElement $domNode, $pa } } } - $parent->addPreserveText(htmlspecialchars($textContent, ENT_QUOTES | ENT_XML1), $fontStyle, $paragraphStyle); + $parent->addPreserveText(htmlspecialchars($textContent, ENT_QUOTES, 'UTF-8'), $fontStyle, $paragraphStyle); } elseif ($xmlReader->elementExists('w:pPr/w:numPr', $domNode)) { // List item $numId = $xmlReader->getAttribute('w:val', $domNode, 'w:pPr/w:numPr/w:numId'); @@ -152,7 +152,7 @@ protected function readParagraph(XMLReader $xmlReader, \DOMElement $domNode, $pa $textContent = null; $nodes = $xmlReader->getElements('w:r', $domNode); if ($nodes->length === 1) { - $textContent = htmlspecialchars($xmlReader->getValue('w:t', $nodes->item(0)), ENT_QUOTES | ENT_XML1); + $textContent = htmlspecialchars($xmlReader->getValue('w:t', $nodes->item(0)), ENT_QUOTES, 'UTF-8'); } else { $textContent = new TextRun($paragraphStyle); foreach ($nodes as $node) { @@ -275,7 +275,7 @@ protected function readRunChild(XMLReader $xmlReader, \DOMElement $node, Abstrac $parent->addText("\t"); } elseif ($node->nodeName == 'w:t' || $node->nodeName == 'w:delText') { // TextRun - $textContent = htmlspecialchars($xmlReader->getValue('.', $node), ENT_QUOTES | ENT_XML1); + $textContent = htmlspecialchars($xmlReader->getValue('.', $node), ENT_QUOTES, 'UTF-8'); if ($runParent->nodeName == 'w:hyperlink') { $rId = $xmlReader->getAttribute('r:id', $runParent); From 45e2e92af7476d54b500271b9bb2d062b9407b2e Mon Sep 17 00:00:00 2001 From: troosan Date: Wed, 21 Mar 2018 21:50:41 +0100 Subject: [PATCH 069/135] fix graph data --- src/PhpWord/Writer/Word2007/Part/Chart.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/Writer/Word2007/Part/Chart.php b/src/PhpWord/Writer/Word2007/Part/Chart.php index 011e34726e..09ce8c5568 100644 --- a/src/PhpWord/Writer/Word2007/Part/Chart.php +++ b/src/PhpWord/Writer/Word2007/Part/Chart.php @@ -236,7 +236,7 @@ private function writeSeriesItem(XMLWriter $xmlWriter, $type, $values) $xmlWriter->startElement('c:pt'); $xmlWriter->writeAttribute('idx', $index); $xmlWriter->startElement('c:v'); - $this->writeText($value); + $xmlWriter->writeText($value); $xmlWriter->endElement(); // c:v $xmlWriter->endElement(); // c:pt $index++; From c08f2718af9c46ef1bcc56a0710487ca543e97d2 Mon Sep 17 00:00:00 2001 From: troosan Date: Wed, 21 Mar 2018 21:58:41 +0100 Subject: [PATCH 070/135] check style fixes --- samples/Sample_32_Chart.php | 10 ++++++++-- src/PhpWord/Writer/Word2007/Part/Chart.php | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/samples/Sample_32_Chart.php b/samples/Sample_32_Chart.php index e345afda12..87d6f3e38f 100644 --- a/samples/Sample_32_Chart.php +++ b/samples/Sample_32_Chart.php @@ -49,8 +49,14 @@ $chartTypes = array('pie', 'bar', 'column', 'line', 'area'); $multiSeries = array('bar', 'column', 'line', 'area'); -$style = array('width' => Converter::cmToEmu(5), 'height' => Converter::cmToEmu(4), '3d' => true, - 'showAxisLabels' => $showAxisLabels, 'showGridX' => $showGridLines, 'showGridY' => $showGridLines); +$style = array( + 'width' => Converter::cmToEmu(5), + 'height' => Converter::cmToEmu(4), + '3d' => true, + 'showAxisLabels' => $showAxisLabels, + 'showGridX' => $showGridLines, + 'showGridY' => $showGridLines, +); foreach ($chartTypes as $chartType) { $section->addTitle(ucfirst($chartType), 2); $chart = $section->addChart($chartType, $categories, $series1, $style); diff --git a/src/PhpWord/Writer/Word2007/Part/Chart.php b/src/PhpWord/Writer/Word2007/Part/Chart.php index 09ce8c5568..59255a6beb 100644 --- a/src/PhpWord/Writer/Word2007/Part/Chart.php +++ b/src/PhpWord/Writer/Word2007/Part/Chart.php @@ -280,7 +280,7 @@ private function writeAxis(XMLWriter $xmlWriter, $type) } $xmlWriter->writeElementBlock('c:crosses', 'val', 'autoZero'); } - if (isset($this->options['radar']) || ($type == "cat" && $style->showGridX()) || ($type == "val" && $style->showGridY())) { + if (isset($this->options['radar']) || ($type == 'cat' && $style->showGridX()) || ($type == 'val' && $style->showGridY())) { $xmlWriter->writeElement('c:majorGridlines'); } From ade497d9d78962caccbf777256be1abfdee7d4f6 Mon Sep 17 00:00:00 2001 From: troosan Date: Wed, 21 Mar 2018 22:19:56 +0100 Subject: [PATCH 071/135] update changelog and doc --- CHANGELOG.md | 1 + docs/ISSUE_TEMPLATE.md | 2 +- docs/elements.rst | 4 +++- docs/styles.rst | 14 ++++++++++++++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c3b4dfd4c..d0b39ce1be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ v0.15.0 (?? ??? 2018) - Added support for Floating Table Positioning (tblpPr) @anrikun #639 - Added support for Image text wrapping distance @troosan #1310 - Added parsing of CSS line-height and text-indent in HTML reader @troosan #1316 +- Added the ability to enable gridlines and axislabels on charts @FrankMeyer #576 ### Fixed - Fix reading of docx default style - @troosan #1238 diff --git a/docs/ISSUE_TEMPLATE.md b/docs/ISSUE_TEMPLATE.md index ee811b00a4..c7ed27d719 100644 --- a/docs/ISSUE_TEMPLATE.md +++ b/docs/ISSUE_TEMPLATE.md @@ -4,7 +4,7 @@ This is: - [ ] a feature request - [ ] **not** a usage question (ask them on https://stackoverflow.com/questions/tagged/phpword) -# Expected Behavior +### Expected Behavior Please describe the behavior you are expecting. diff --git a/docs/elements.rst b/docs/elements.rst index 4c5ad03b70..8f33b5035b 100644 --- a/docs/elements.rst +++ b/docs/elements.rst @@ -448,7 +448,9 @@ Charts can be added using $categories = array('A', 'B', 'C', 'D', 'E'); $series = array(1, 3, 2, 5, 4); - $chart = $section->addChart('line', $categories, $series); + $chart = $section->addChart('line', $categories, $series, $style); + +For available styling options see :ref:`chart-style`. check out the Sample_32_Chart.php for more options and styling. diff --git a/docs/styles.rst b/docs/styles.rst index 9b3ce75819..0bda3faf09 100644 --- a/docs/styles.rst +++ b/docs/styles.rst @@ -178,3 +178,17 @@ Available NumberingLevel style options: - ``suffix``. Content between numbering symbol and paragraph text tab\|space\|nothing. - ``tabPos``. See paragraph style. - ``text``. Numbering level text e.g. %1 for nonbullet or bullet character. + +.. _chart-style: + +Chart +----- + +Available Chart style options: + +- ``width``. Width (in EMU). +- ``height``. Height (in EMU). +- ``3d``. Is 3D; applies to pie, bar, line, area, *true* or *false*. +- ``showAxisLabels``. Show labels for axis, *true* or *false*. +- ``gridX``. Show Gridlines for X-Axis, *true* or *false*. +- ``gridY``. Show Gridlines for Y-Axis, *true* or *false*. From 400ee57bee82faaa3745f51a02ef6f1f6fa52b62 Mon Sep 17 00:00:00 2001 From: troosan Date: Thu, 22 Mar 2018 22:47:27 +0100 Subject: [PATCH 072/135] fix --- src/PhpWord/Writer/Word2007/Part/Chart.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/Writer/Word2007/Part/Chart.php b/src/PhpWord/Writer/Word2007/Part/Chart.php index 59255a6beb..2aeccca02d 100644 --- a/src/PhpWord/Writer/Word2007/Part/Chart.php +++ b/src/PhpWord/Writer/Word2007/Part/Chart.php @@ -236,7 +236,7 @@ private function writeSeriesItem(XMLWriter $xmlWriter, $type, $values) $xmlWriter->startElement('c:pt'); $xmlWriter->writeAttribute('idx', $index); $xmlWriter->startElement('c:v'); - $xmlWriter->writeText($value); + $xmlWriter->text($value); $xmlWriter->endElement(); // c:v $xmlWriter->endElement(); // c:pt $index++; From 34bda105365cc4c8d9e8fe9c33f3d8b204c4ee79 Mon Sep 17 00:00:00 2001 From: gthomas2 Date: Tue, 6 Jan 2015 17:20:27 +0000 Subject: [PATCH 073/135] Fix images added in word 2011 --- src/PhpWord/Element/Image.php | 20 +++++++++++++++++++- src/PhpWord/Reader/Word2007/AbstractPart.php | 9 +++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/PhpWord/Element/Image.php b/src/PhpWord/Element/Image.php index 0363706782..0eb3d93732 100644 --- a/src/PhpWord/Element/Image.php +++ b/src/PhpWord/Element/Image.php @@ -65,6 +65,13 @@ class Image extends AbstractElement */ private $watermark; + /** + * Name of image + * + * @var string + */ + private $name; + /** * Image type * @@ -131,11 +138,12 @@ class Image extends AbstractElement * @throws \PhpOffice\PhpWord\Exception\InvalidImageException * @throws \PhpOffice\PhpWord\Exception\UnsupportedImageTypeException */ - public function __construct($source, $style = null, $watermark = false) + public function __construct($source, $style = null, $watermark = false, $name = null) { $this->source = $source; $this->setIsWatermark($watermark); $this->style = $this->setNewStyle(new ImageStyle(), $style, true); + $this->name = $name; $this->checkImage(); } @@ -170,6 +178,16 @@ public function getSourceType() return $this->sourceType; } + /** + * Get image name + * + * @return null|string + */ + public function getName() + { + return $this->name; + } + /** * Get image media ID * diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index f64886cfda..d8155eb500 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -260,6 +260,15 @@ protected function readRunChild(XMLReader $xmlReader, \DOMElement $node, Abstrac } $parent->addImage($imageSource); } + } elseif ($node->nodeName == 'w:drawing') { + // Office 2011 Images + $name = $xmlReader->getAttribute('name', $node, 'wp:inline/a:graphic/a:graphicData/pic:pic/pic:nvPicPr/pic:cNvPr'); + $embedId = $xmlReader->getAttribute('r:embed', $node, 'wp:inline/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip'); + $target = $this->getMediaTarget($docPart, $embedId); + if (!is_null($target)) { + $imageSource = "zip://{$this->docFile}#{$target}"; + $parent->addImage($imageSource, null, false, $name); + } } elseif ($node->nodeName == 'w:object') { // Object $rId = $xmlReader->getAttribute('r:id', $node, 'o:OLEObject'); From 9b722a5b0cc03e7e46390fba9c011c88e0dca46d Mon Sep 17 00:00:00 2001 From: gthomas2 Date: Tue, 6 Jan 2015 17:36:11 +0000 Subject: [PATCH 074/135] Added missing namespaces --- src/PhpWord/Shared/XMLReader.php | 195 +++++++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 src/PhpWord/Shared/XMLReader.php diff --git a/src/PhpWord/Shared/XMLReader.php b/src/PhpWord/Shared/XMLReader.php new file mode 100644 index 0000000000..44ee07cd71 --- /dev/null +++ b/src/PhpWord/Shared/XMLReader.php @@ -0,0 +1,195 @@ +open($zipFile); + $content = $zip->getFromName($xmlFile); + $zip->close(); + + if ($content === false) { + return false; + } else { + return $this->getDomFromString($content); + } + } + + /** + * Get DOMDocument from content string + * + * @param string $content + * @return \DOMDocument + */ + public function getDomFromString($content) + { + $this->dom = new \DOMDocument(); + $this->dom->loadXML($content); + + return $this->dom; + } + + /** + * Get elements + * + * @param string $path + * @param \DOMElement $contextNode + * @return \DOMNodeList + */ + public function getElements($path, \DOMElement $contextNode = null) + { + if ($this->dom === null) { + return array(); + } + if ($this->xpath === null) { + $this->xpath = new \DOMXpath($this->dom); + // GT Mod - required for reading images + $this->xpath->registerNamespace('a', 'http://schemas.openxmlformats.org/drawingml/2006/main'); + $this->xpath->registerNamespace('pic', 'http://schemas.openxmlformats.org/drawingml/2006/picture'); + } + + if (is_null($contextNode)) { + return $this->xpath->query($path); + } else { + return $this->xpath->query($path, $contextNode); + } + } + + /** + * Get element + * + * @param string $path + * @param \DOMElement $contextNode + * @return \DOMElement|null + */ + public function getElement($path, \DOMElement $contextNode = null) + { + $elements = $this->getElements($path, $contextNode); + if ($elements->length > 0) { + return $elements->item(0); + } else { + return null; + } + } + + /** + * Get element attribute + * + * @param string $attribute + * @param \DOMElement $contextNode + * @param string $path + * @return string|null + */ + public function getAttribute($attribute, \DOMElement $contextNode = null, $path = null) + { + $return = null; + if ($path !== null) { + $elements = $this->getElements($path, $contextNode); + if ($elements->length > 0) { + /** @var \DOMElement $node Type hint */ + $node = $elements->item(0); + $return = $node->getAttribute($attribute); + } + } else { + if ($contextNode !== null) { + $return = $contextNode->getAttribute($attribute); + } + } + + return ($return == '') ? null : $return; + } + + /** + * Get element value + * + * @param string $path + * @param \DOMElement $contextNode + * @return string|null + */ + public function getValue($path, \DOMElement $contextNode = null) + { + $elements = $this->getElements($path, $contextNode); + if ($elements->length > 0) { + return $elements->item(0)->nodeValue; + } else { + return null; + } + } + + /** + * Count elements + * + * @param string $path + * @param \DOMElement $contextNode + * @return integer + */ + public function countElements($path, \DOMElement $contextNode = null) + { + $elements = $this->getElements($path, $contextNode); + + return $elements->length; + } + + /** + * Element exists + * + * @param string $path + * @param \DOMElement $contextNode + * @return boolean + */ + public function elementExists($path, \DOMElement $contextNode = null) + { + return $this->getElements($path, $contextNode)->length > 0; + } +} From 566e625b85b80f503db69d3e0e635a817dc0ef10 Mon Sep 17 00:00:00 2001 From: troosan Date: Sun, 25 Mar 2018 22:46:50 +0200 Subject: [PATCH 075/135] merge/add test/cleanup --- composer.json | 2 +- src/PhpWord/Element/AbstractContainer.php | 2 +- src/PhpWord/Element/Image.php | 15 +- src/PhpWord/Reader/Word2007/AbstractPart.php | 9 +- src/PhpWord/Shared/XMLReader.php | 195 ------------------ tests/PhpWord/Reader/Word2007/ElementTest.php | 36 ++++ tests/PhpWord/Reader/Word2007Test.php | 14 ++ .../PhpWord/_files/documents/reader-2011.docx | Bin 0 -> 36938 bytes 8 files changed, 73 insertions(+), 200 deletions(-) delete mode 100644 src/PhpWord/Shared/XMLReader.php create mode 100644 tests/PhpWord/_files/documents/reader-2011.docx diff --git a/composer.json b/composer.json index 742e4bc8b4..6dc9be2c68 100644 --- a/composer.json +++ b/composer.json @@ -61,7 +61,7 @@ "php": "^5.3.3 || ^7.0", "ext-xml": "*", "zendframework/zend-escaper": "^2.2", - "phpoffice/common": "^0.2" + "phpoffice/common": "dev-develop" }, "require-dev": { "phpunit/phpunit": "^4.8.36 || ^5.0", diff --git a/src/PhpWord/Element/AbstractContainer.php b/src/PhpWord/Element/AbstractContainer.php index ec990720f5..204d4a7399 100644 --- a/src/PhpWord/Element/AbstractContainer.php +++ b/src/PhpWord/Element/AbstractContainer.php @@ -35,7 +35,7 @@ * @method TOC addTOC(mixed $fontStyle = null, mixed $tocStyle = null, int $minDepth = 1, int $maxDepth = 9) * @method PageBreak addPageBreak() * @method Table addTable(mixed $style = null) - * @method Image addImage(string $source, mixed $style = null, bool $isWatermark = false) + * @method Image addImage(string $source, mixed $style = null, bool $isWatermark = false, $name = null) * @method OLEObject addOLEObject(string $source, mixed $style = null) * @method TextBox addTextBox(mixed $style = null) * @method Field addField(string $type = null, array $properties = array(), array $options = array(), mixed $text = null) diff --git a/src/PhpWord/Element/Image.php b/src/PhpWord/Element/Image.php index 0eb3d93732..bae87ff5d8 100644 --- a/src/PhpWord/Element/Image.php +++ b/src/PhpWord/Element/Image.php @@ -134,6 +134,7 @@ class Image extends AbstractElement * @param string $source * @param mixed $style * @param bool $watermark + * @param string $name * * @throws \PhpOffice\PhpWord\Exception\InvalidImageException * @throws \PhpOffice\PhpWord\Exception\UnsupportedImageTypeException @@ -141,9 +142,9 @@ class Image extends AbstractElement public function __construct($source, $style = null, $watermark = false, $name = null) { $this->source = $source; - $this->setIsWatermark($watermark); $this->style = $this->setNewStyle(new ImageStyle(), $style, true); - $this->name = $name; + $this->setIsWatermark($watermark); + $this->setName($name); $this->checkImage(); } @@ -178,6 +179,16 @@ public function getSourceType() return $this->sourceType; } + /** + * Sets the image name + * + * @param string $value + */ + public function setName($value) + { + $this->name = $value; + } + /** * Get image name * diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index d8155eb500..c7ec4ca742 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -261,7 +261,12 @@ protected function readRunChild(XMLReader $xmlReader, \DOMElement $node, Abstrac $parent->addImage($imageSource); } } elseif ($node->nodeName == 'w:drawing') { - // Office 2011 Images + // Office 2011 Image + $xmlReader->registerNamespace('wp', 'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing'); + $xmlReader->registerNamespace('r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + $xmlReader->registerNamespace('pic', 'http://schemas.openxmlformats.org/drawingml/2006/picture'); + $xmlReader->registerNamespace('a', 'http://schemas.openxmlformats.org/drawingml/2006/main'); + $name = $xmlReader->getAttribute('name', $node, 'wp:inline/a:graphic/a:graphicData/pic:pic/pic:nvPicPr/pic:cNvPr'); $embedId = $xmlReader->getAttribute('r:embed', $node, 'wp:inline/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip'); $target = $this->getMediaTarget($docPart, $embedId); @@ -573,6 +578,8 @@ private function findPossibleAttribute(XMLReader $xmlReader, \DOMElement $node, return $possibleAttribute; } } + + return null; } return $attributes; diff --git a/src/PhpWord/Shared/XMLReader.php b/src/PhpWord/Shared/XMLReader.php deleted file mode 100644 index 44ee07cd71..0000000000 --- a/src/PhpWord/Shared/XMLReader.php +++ /dev/null @@ -1,195 +0,0 @@ -open($zipFile); - $content = $zip->getFromName($xmlFile); - $zip->close(); - - if ($content === false) { - return false; - } else { - return $this->getDomFromString($content); - } - } - - /** - * Get DOMDocument from content string - * - * @param string $content - * @return \DOMDocument - */ - public function getDomFromString($content) - { - $this->dom = new \DOMDocument(); - $this->dom->loadXML($content); - - return $this->dom; - } - - /** - * Get elements - * - * @param string $path - * @param \DOMElement $contextNode - * @return \DOMNodeList - */ - public function getElements($path, \DOMElement $contextNode = null) - { - if ($this->dom === null) { - return array(); - } - if ($this->xpath === null) { - $this->xpath = new \DOMXpath($this->dom); - // GT Mod - required for reading images - $this->xpath->registerNamespace('a', 'http://schemas.openxmlformats.org/drawingml/2006/main'); - $this->xpath->registerNamespace('pic', 'http://schemas.openxmlformats.org/drawingml/2006/picture'); - } - - if (is_null($contextNode)) { - return $this->xpath->query($path); - } else { - return $this->xpath->query($path, $contextNode); - } - } - - /** - * Get element - * - * @param string $path - * @param \DOMElement $contextNode - * @return \DOMElement|null - */ - public function getElement($path, \DOMElement $contextNode = null) - { - $elements = $this->getElements($path, $contextNode); - if ($elements->length > 0) { - return $elements->item(0); - } else { - return null; - } - } - - /** - * Get element attribute - * - * @param string $attribute - * @param \DOMElement $contextNode - * @param string $path - * @return string|null - */ - public function getAttribute($attribute, \DOMElement $contextNode = null, $path = null) - { - $return = null; - if ($path !== null) { - $elements = $this->getElements($path, $contextNode); - if ($elements->length > 0) { - /** @var \DOMElement $node Type hint */ - $node = $elements->item(0); - $return = $node->getAttribute($attribute); - } - } else { - if ($contextNode !== null) { - $return = $contextNode->getAttribute($attribute); - } - } - - return ($return == '') ? null : $return; - } - - /** - * Get element value - * - * @param string $path - * @param \DOMElement $contextNode - * @return string|null - */ - public function getValue($path, \DOMElement $contextNode = null) - { - $elements = $this->getElements($path, $contextNode); - if ($elements->length > 0) { - return $elements->item(0)->nodeValue; - } else { - return null; - } - } - - /** - * Count elements - * - * @param string $path - * @param \DOMElement $contextNode - * @return integer - */ - public function countElements($path, \DOMElement $contextNode = null) - { - $elements = $this->getElements($path, $contextNode); - - return $elements->length; - } - - /** - * Element exists - * - * @param string $path - * @param \DOMElement $contextNode - * @return boolean - */ - public function elementExists($path, \DOMElement $contextNode = null) - { - return $this->getElements($path, $contextNode)->length > 0; - } -} diff --git a/tests/PhpWord/Reader/Word2007/ElementTest.php b/tests/PhpWord/Reader/Word2007/ElementTest.php index 75060625fd..cb72ef9f0a 100644 --- a/tests/PhpWord/Reader/Word2007/ElementTest.php +++ b/tests/PhpWord/Reader/Word2007/ElementTest.php @@ -236,4 +236,40 @@ public function testReadTitleStyle() $this->assertEquals('Title', $formattedTitle->getStyle()); $this->assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $formattedTitle->getText()); } + + /** + * Test reading Drawing + */ + public function testReadDrawing() + { + $documentXml = ' + + + + + + + + + + + + + + + + + + + + + + + '; + + $phpWord = $this->getDocumentFromString(array('document' => $documentXml)); + + $elements = $phpWord->getSection(0)->getElements(); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $elements[0]); + } } diff --git a/tests/PhpWord/Reader/Word2007Test.php b/tests/PhpWord/Reader/Word2007Test.php index 62d23a6873..e4ea62de36 100644 --- a/tests/PhpWord/Reader/Word2007Test.php +++ b/tests/PhpWord/Reader/Word2007Test.php @@ -64,4 +64,18 @@ public function testLoad() $doc = TestHelperDOCX::getDocument($phpWord); $this->assertFalse($doc->elementExists('/w:document/w:body/w:p/w:r[w:t/node()="italics"]/w:rPr/w:b')); } + + /** + * Load a Word 2011 file + */ + public function testLoadWord2011() + { + $filename = __DIR__ . '/../_files/documents/reader-2011.docx'; + $phpWord = IOFactory::load($filename); + + $this->assertInstanceOf('PhpOffice\\PhpWord\\PhpWord', $phpWord); + + $doc = TestHelperDOCX::getDocument($phpWord); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p[3]/w:r/w:pict/v:shape/v:imagedata')); + } } diff --git a/tests/PhpWord/_files/documents/reader-2011.docx b/tests/PhpWord/_files/documents/reader-2011.docx new file mode 100644 index 0000000000000000000000000000000000000000..be94eca5242caeb7c9beda45741d5bcfd3b5838e GIT binary patch literal 36938 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%0AfwqU0&g5gH4Gl!~;>i>16+#cyIzb&8cM|zK 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 Date: Mon, 2 Apr 2018 14:47:18 +0200 Subject: [PATCH 076/135] update samples instructions [ci skip] --- docs/installing.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/installing.rst b/docs/installing.rst index 4f407f54a4..34353be8ae 100644 --- a/docs/installing.rst +++ b/docs/installing.rst @@ -54,7 +54,5 @@ Example: Using samples ------------- -After installation, you can browse and use the samples that we've -provided, either by command line or using browser. If you can access -your PHPWord library folder using browser, point your browser to the -``samples`` folder, e.g. ``http://localhost/PhpWord/samples/``. +More examples are provided in the ``samples`` directory. +For an easy access to those samples launch ``php -S localhost:8000`` in the samples directory then browse to http://localhost:8000 to view the samples. From 67b18c32e7e4fa0bb0fa5cbe5c14efdf06437a91 Mon Sep 17 00:00:00 2001 From: troosan Date: Mon, 2 Apr 2018 14:50:31 +0200 Subject: [PATCH 077/135] fix [ci skip] --- samples/Sample_Header.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/Sample_Header.php b/samples/Sample_Header.php index ac51f983ee..faa39a359e 100644 --- a/samples/Sample_Header.php +++ b/samples/Sample_Header.php @@ -83,7 +83,7 @@ function write($phpWord, $filename, $writers) $result .= EOL; } - $result .= getEndingNotes($writers); + $result .= getEndingNotes($writers, $filename); return $result; } @@ -95,7 +95,7 @@ function write($phpWord, $filename, $writers) * * @return string */ -function getEndingNotes($writers) +function getEndingNotes($writers, $filename) { $result = ''; From ca82e19bba2e81f32530292b53f95cf623268c58 Mon Sep 17 00:00:00 2001 From: Sam Date: Sat, 7 Apr 2018 11:24:52 +0200 Subject: [PATCH 078/135] support internal link in addHtml method --- src/PhpWord/Shared/Html.php | 6 +++++- tests/PhpWord/Shared/HtmlTest.php | 12 ++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 0f5f446aee..caa49034a1 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -664,6 +664,10 @@ private static function parseLink($node, $element, &$styles) } self::parseInlineStyle($node, $styles['font']); - return $element->addLink($target, $node->textContent, $styles['font'], $styles['paragraph']); + if(strpos($target, '#') === 0) { + return $element->addLink(substr($target, 1), $node->textContent, $styles['font'], $styles['paragraph'], true); + } else { + return $element->addLink($target, $node->textContent, $styles['font'], $styles['paragraph']); + } } } diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index 6122924ff0..2c4960810e 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -353,5 +353,17 @@ public function testParseLink() $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:hyperlink')); $this->assertEquals('link text', $doc->getElement('/w:document/w:body/w:p/w:hyperlink/w:r/w:t')->nodeValue); + + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + $section->addBookmark('bookmark'); + $html = '

        internal link text

        '; + Html::addHtml($section, $html); + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:hyperlink')); + $this->assertTrue($doc->getElement('/w:document/w:body/w:p/w:hyperlink')->hasAttribute('w:anchor')); + $this->assertEquals('bookmark', $doc->getElement('/w:document/w:body/w:p/w:hyperlink')->getAttribute('w:anchor')); + } } From a7981717b343dd09ece3962d36ebaf15e6852c4b Mon Sep 17 00:00:00 2001 From: pcworld <0188801@gmail.com> Date: Mon, 9 Apr 2018 02:45:50 +0200 Subject: [PATCH 079/135] addImage docs: Warn about user-generated strings --- docs/elements.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/elements.rst b/docs/elements.rst index c73ffa0645..f2637ac9bb 100644 --- a/docs/elements.rst +++ b/docs/elements.rst @@ -234,7 +234,7 @@ To add an image, use the ``addImage`` method to sections, headers, footers, text $section->addImage($src, [$style]); -- ``$src``. String path to a local image, URL of a remote image or the image data, as a string. +- ``$src``. String path to a local image, URL of a remote image or the image data, as a string. Warning: Do not pass user-generated strings here, as that would allow an attacker to read arbitrary files or perform server-side request forgery by passing file paths or URLs instead of image data. - ``$style``. See :ref:`image-style`. Examples: From 6253adaba15a72f5310970d180e7f5b1c13a3242 Mon Sep 17 00:00:00 2001 From: pcworld <0188801@gmail.com> Date: Mon, 9 Apr 2018 02:47:16 +0200 Subject: [PATCH 080/135] Warn about parsing user-generated HTML --- src/PhpWord/Shared/Html.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index d8a10b5702..3f34968dcb 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -34,6 +34,8 @@ class Html * Add HTML parts. * * Note: $stylesheet parameter is removed to avoid PHPMD error for unused parameter + * Warning: Do not pass user-generated HTML here, as that would allow an attacker to read arbitrary + * files or perform server-side request forgery by passing local file paths or URLs in . * * @param \PhpOffice\PhpWord\Element\AbstractContainer $element Where the parts need to be added * @param string $html The code to parse From e885b371bc4793fc43ed6d8c4586cd537f810b01 Mon Sep 17 00:00:00 2001 From: Frank Liepert Date: Tue, 10 Apr 2018 20:30:04 +0200 Subject: [PATCH 081/135] Add missing param annotation --- samples/Sample_Header.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/Sample_Header.php b/samples/Sample_Header.php index faa39a359e..f0fc626627 100644 --- a/samples/Sample_Header.php +++ b/samples/Sample_Header.php @@ -92,7 +92,7 @@ function write($phpWord, $filename, $writers) * Get ending notes * * @param array $writers - * + * @param mixed $filename * @return string */ function getEndingNotes($writers, $filename) From 081c6722f62aa15a88af8fdff8dca3b58b136bb8 Mon Sep 17 00:00:00 2001 From: Frank Liepert Date: Wed, 11 Apr 2018 09:56:02 +0200 Subject: [PATCH 082/135] Add support for table indent --- CHANGELOG.md | 1 + docs/styles.rst | 1 + src/PhpWord/ComplexType/TblWidth.php | 59 +++++++++++++++++++ src/PhpWord/Reader/Word2007/AbstractPart.php | 24 ++++++++ src/PhpWord/Style/Table.php | 24 ++++++++ src/PhpWord/Writer/Word2007/Style/Table.php | 16 +++++ tests/PhpWord/Reader/Word2007/StyleTest.php | 19 ++++++ tests/PhpWord/Style/TableTest.php | 11 ++++ .../Writer/Word2007/Style/TableTest.php | 25 +++++++- 9 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 src/PhpWord/ComplexType/TblWidth.php diff --git a/CHANGELOG.md b/CHANGELOG.md index d0b39ce1be..e1d0937f2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ v0.15.0 (?? ??? 2018) - Added support for Image text wrapping distance @troosan #1310 - Added parsing of CSS line-height and text-indent in HTML reader @troosan #1316 - Added the ability to enable gridlines and axislabels on charts @FrankMeyer #576 +- Add support for table indent (tblInd) @Trainmaster ### Fixed - Fix reading of docx default style - @troosan #1238 diff --git a/docs/styles.rst b/docs/styles.rst index 0bda3faf09..88caeaeb3e 100644 --- a/docs/styles.rst +++ b/docs/styles.rst @@ -104,6 +104,7 @@ Available Table style options: - ``border(Top|Right|Bottom|Left)Color``. Border color, e.g. '9966CC'. - ``border(Top|Right|Bottom|Left)Size``. Border size in *twip*. - ``cellMargin(Top|Right|Bottom|Left)``. Cell margin in *twip*. +- ``indent``. Table indent from leading margin. Must be an instance of ``\PhpOffice\PhpWord\ComplexType\TblWidth``. - ``width``. Table width in percent. - ``unit``. The unit to use for the width. One of ``\PhpOffice\PhpWord\SimpleType\TblWidth``. Defaults to *auto*. - ``layout``. Table layout, either *fixed* or *autofit* See ``\PhpOffice\PhpWord\Style\Table`` for constants. diff --git a/src/PhpWord/ComplexType/TblWidth.php b/src/PhpWord/ComplexType/TblWidth.php new file mode 100644 index 0000000000..91dedc3ded --- /dev/null +++ b/src/PhpWord/ComplexType/TblWidth.php @@ -0,0 +1,59 @@ +value = $value; + TblWidthSimpleType::validate($type); + $this->type = $type; + } + + /** + * @return string + */ + public function getType() + { + return $this->type; + } + + /** + * @return int + */ + public function getValue() + { + return $this->value; + } +} diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index f64886cfda..48a84ff2db 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -18,6 +18,7 @@ namespace PhpOffice\PhpWord\Reader\Word2007; use PhpOffice\Common\XMLReader; +use PhpOffice\PhpWord\ComplexType\TblWidth as TblWidthComplexType; use PhpOffice\PhpWord\Element\AbstractContainer; use PhpOffice\PhpWord\Element\TextRun; use PhpOffice\PhpWord\Element\TrackChange; @@ -472,6 +473,11 @@ protected function readTableStyle(XMLReader $xmlReader, \DOMElement $domNode) if ($tablePositionNode !== null) { $style['position'] = $this->readTablePosition($xmlReader, $tablePositionNode); } + + $indentNode = $xmlReader->getElement('w:tblInd', $styleNode); + if ($indentNode !== null) { + $style['indent'] = $this->readTableIndent($xmlReader, $indentNode); + } } } @@ -503,6 +509,24 @@ private function readTablePosition(XMLReader $xmlReader, \DOMElement $domNode) return $this->readStyleDefs($xmlReader, $domNode, $styleDefs); } + /** + * Read w:tblInd + * + * @param \PhpOffice\Common\XMLReader $xmlReader + * @param \DOMElement $domNode + * @return TblWidthComplexType + */ + private function readTableIndent(XMLReader $xmlReader, \DOMElement $domNode) + { + $styleDefs = array( + 'value' => array(self::READ_VALUE, '.', 'w:w'), + 'type' => array(self::READ_VALUE, '.', 'w:type'), + ); + $styleDefs = $this->readStyleDefs($xmlReader, $domNode, $styleDefs); + + return new TblWidthComplexType((int) $styleDefs['value'], $styleDefs['type']); + } + /** * Read w:tcPr * diff --git a/src/PhpWord/Style/Table.php b/src/PhpWord/Style/Table.php index feb028da2c..b622c78b4a 100644 --- a/src/PhpWord/Style/Table.php +++ b/src/PhpWord/Style/Table.php @@ -17,6 +17,7 @@ namespace PhpOffice\PhpWord\Style; +use PhpOffice\PhpWord\ComplexType\TblWidth as TblWidthComplexType; use PhpOffice\PhpWord\SimpleType\Jc; use PhpOffice\PhpWord\SimpleType\JcTable; use PhpOffice\PhpWord\SimpleType\TblWidth; @@ -159,6 +160,9 @@ class Table extends Border */ private $position; + /** @var TblWidthComplexType|null */ + private $indent; + /** * Create new table style * @@ -724,4 +728,24 @@ public function setPosition($value = null) return $this; } + + /** + * @return TblWidthComplexType + */ + public function getIndent() + { + return $this->indent; + } + + /** + * @param TblWidthComplexType $indent + * @return self + * @see http://www.datypic.com/sc/ooxml/e-w_tblInd-1.html + */ + public function setIndent(TblWidthComplexType $indent) + { + $this->indent = $indent; + + return $this; + } } diff --git a/src/PhpWord/Writer/Word2007/Style/Table.php b/src/PhpWord/Writer/Word2007/Style/Table.php index eb5af86da6..7f49be7c38 100644 --- a/src/PhpWord/Writer/Word2007/Style/Table.php +++ b/src/PhpWord/Writer/Word2007/Style/Table.php @@ -79,6 +79,7 @@ private function writeStyle(XMLWriter $xmlWriter, TableStyle $style) $this->writeTblWidth($xmlWriter, 'w:tblW', $style->getUnit(), $style->getWidth()); $this->writeTblWidth($xmlWriter, 'w:tblCellSpacing', TblWidth::TWIP, $style->getCellSpacing()); + $this->writeIndent($xmlWriter, $style); $this->writeLayout($xmlWriter, $style->getLayout()); // Position @@ -216,4 +217,19 @@ public function setWidth($value = null) { $this->width = $value; } + + /** + * @param XMLWriter $xmlWriter + * @param TableStyle $style + */ + private function writeIndent(XMLWriter $xmlWriter, TableStyle $style) + { + $indent = $style->getIndent(); + + if ($indent === null) { + return; + } + + $this->writeTblWidth($xmlWriter, 'w:tblInd', $indent->getType(), $indent->getValue()); + } } diff --git a/tests/PhpWord/Reader/Word2007/StyleTest.php b/tests/PhpWord/Reader/Word2007/StyleTest.php index 9bb6d3bdbd..d64079fa0e 100644 --- a/tests/PhpWord/Reader/Word2007/StyleTest.php +++ b/tests/PhpWord/Reader/Word2007/StyleTest.php @@ -126,4 +126,23 @@ public function testReadPosition() $fontStyle = $textRun->getElement(0)->getFontStyle(); $this->assertEquals(15, $fontStyle->getPosition()); } + + public function testReadIndent() + { + $documentXml = ' + + + + '; + + $phpWord = $this->getDocumentFromString(array('document' => $documentXml)); + + $elements = $phpWord->getSection(0)->getElements(); + $this->assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]); + $this->assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle()); + /** @var \PhpOffice\PhpWord\Style\Table $tableStyle */ + $tableStyle = $elements[0]->getStyle(); + $this->assertSame(TblWidth::TWIP, $tableStyle->getIndent()->getType()); + $this->assertSame(2160, $tableStyle->getIndent()->getValue()); + } } diff --git a/tests/PhpWord/Style/TableTest.php b/tests/PhpWord/Style/TableTest.php index 332d31aac8..91fc35509c 100644 --- a/tests/PhpWord/Style/TableTest.php +++ b/tests/PhpWord/Style/TableTest.php @@ -17,6 +17,7 @@ namespace PhpOffice\PhpWord\Style; +use PhpOffice\PhpWord\ComplexType\TblWidth as TblWidthComplexType; use PhpOffice\PhpWord\SimpleType\JcTable; use PhpOffice\PhpWord\SimpleType\TblWidth; @@ -57,6 +58,7 @@ public function testDefaultValues() $this->assertNull($object->getBgColor()); $this->assertEquals(Table::LAYOUT_AUTO, $object->getLayout()); $this->assertEquals(TblWidth::AUTO, $object->getUnit()); + $this->assertNull($object->getIndent()); } /** @@ -208,4 +210,13 @@ public function testTablePosition() $this->assertNotNull($object->getPosition()); $this->assertEquals(TablePosition::VANCHOR_PAGE, $object->getPosition()->getVertAnchor()); } + + public function testIndent() + { + $indent = new TblWidthComplexType(100, TblWidth::TWIP); + + $table = new Table(array('indent' => $indent)); + + $this->assertSame($indent, $table->getIndent()); + } } diff --git a/tests/PhpWord/Writer/Word2007/Style/TableTest.php b/tests/PhpWord/Writer/Word2007/Style/TableTest.php index 364a34d63b..ec3b2483b1 100644 --- a/tests/PhpWord/Writer/Word2007/Style/TableTest.php +++ b/tests/PhpWord/Writer/Word2007/Style/TableTest.php @@ -17,6 +17,8 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Style; +use PhpOffice\PhpWord\ComplexType\TblWidth as TblWidthComplexType; +use PhpOffice\PhpWord\SimpleType\TblWidth; use PhpOffice\PhpWord\Style\Table; use PhpOffice\PhpWord\Style\TablePosition; use PhpOffice\PhpWord\TestHelperDOCX; @@ -75,7 +77,7 @@ public function testCellSpacing() $path = '/w:document/w:body/w:tbl/w:tblPr/w:tblCellSpacing'; $this->assertTrue($doc->elementExists($path)); $this->assertEquals(10.3, $doc->getElementAttribute($path, 'w:w')); - $this->assertEquals(\PhpOffice\PhpWord\SimpleType\TblWidth::TWIP, $doc->getElementAttribute($path, 'w:type')); + $this->assertEquals(TblWidth::TWIP, $doc->getElementAttribute($path, 'w:type')); } /** @@ -118,4 +120,25 @@ public function testTablePosition() $this->assertEquals(TablePosition::YALIGN_TOP, $doc->getElementAttribute($path, 'w:tblpYSpec')); $this->assertEquals(60, $doc->getElementAttribute($path, 'w:tblpY')); } + + public function testIndent() + { + $value = 100; + $type = TblWidth::TWIP; + + $tableStyle = new Table(); + $tableStyle->setIndent(new TblWidthComplexType($value, $type)); + + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + $table = $section->addTable($tableStyle); + $table->addRow(); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $path = '/w:document/w:body/w:tbl/w:tblPr/w:tblInd'; + $this->assertTrue($doc->elementExists($path)); + $this->assertSame($value, (int) $doc->getElementAttribute($path, 'w:w')); + $this->assertSame($type, $doc->getElementAttribute($path, 'w:type')); + } } From 853fcec1b6a20a7c5e75eeac1a33ad33a07ef527 Mon Sep 17 00:00:00 2001 From: Frank Liepert Date: Tue, 10 Apr 2018 11:18:37 +0200 Subject: [PATCH 083/135] Fix documented unit for image height/width --- CHANGELOG.md | 1 + docs/styles.rst | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0b39ce1be..7dcefac29b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ v0.15.0 (?? ??? 2018) ### Changed - Remove zend-stdlib dependency @Trainmaster #1284 +- The default unit for `\PhpOffice\PhpWord\Style\Image` changed from `px` to `pt`. v0.14.0 (29 Dec 2017) diff --git a/docs/styles.rst b/docs/styles.rst index 0bda3faf09..8cb6fa23d0 100644 --- a/docs/styles.rst +++ b/docs/styles.rst @@ -149,10 +149,10 @@ Image Available Image style options: - ``alignment``. See ``\PhpOffice\PhpWord\SimpleType\Jc`` class for the details. -- ``height``. Height in pixels. +- ``height``. Height in *pt*. - ``marginLeft``. Left margin in inches, can be negative. - ``marginTop``. Top margin in inches, can be negative. -- ``width``. Width in pixels. +- ``width``. Width in *pt*. - ``wrappingStyle``. Wrapping style, *inline*, *square*, *tight*, *behind*, or *infront*. - ``wrapDistanceTop``. Top text wrapping in pixels. - ``wrapDistanceBottom``. Bottom text wrapping in pixels. From 833cf07c1acfe86b4bb5ca9786692a59991f2643 Mon Sep 17 00:00:00 2001 From: Frank Liepert Date: Tue, 10 Apr 2018 11:19:15 +0200 Subject: [PATCH 084/135] Consistently format "pt" unit --- docs/elements.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/elements.rst b/docs/elements.rst index 8f33b5035b..dd398e4669 100644 --- a/docs/elements.rst +++ b/docs/elements.rst @@ -435,8 +435,8 @@ Available line style attributes: - ``dash``. Line types: dash, rounddot, squaredot, dashdot, longdash, longdashdot, longdashdotdot. - ``beginArrow``. Start type of arrow: block, open, classic, diamond, oval. - ``endArrow``. End type of arrow: block, open, classic, diamond, oval. -- ``width``. Line-object width in pt. -- ``height``. Line-object height in pt. +- ``width``. Line-object width in *pt*. +- ``height``. Line-object height in *pt*. - ``flip``. Flip the line element: true, false. Chart From 9bc85347ef074a2e4c3bf983e2b68c235adefc02 Mon Sep 17 00:00:00 2001 From: troosan Date: Sat, 14 Apr 2018 21:15:36 +0200 Subject: [PATCH 085/135] fix code formatting --- CHANGELOG.md | 1 + src/PhpWord/Shared/Html.php | 8 ++++---- tests/PhpWord/Shared/HtmlTest.php | 3 +-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dcefac29b..fb07fcc243 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ v0.15.0 (?? ??? 2018) - Added support for Image text wrapping distance @troosan #1310 - Added parsing of CSS line-height and text-indent in HTML reader @troosan #1316 - Added the ability to enable gridlines and axislabels on charts @FrankMeyer #576 +- Added parsing of internal links in HTML reader @lalop #1336 ### Fixed - Fix reading of docx default style - @troosan #1238 diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index e27e706e79..7d8ee51f1d 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -723,10 +723,10 @@ private static function parseLink($node, $element, &$styles) } self::parseInlineStyle($node, $styles['font']); - if(strpos($target, '#') === 0) { - return $element->addLink(substr($target, 1), $node->textContent, $styles['font'], $styles['paragraph'], true); - } else { - return $element->addLink($target, $node->textContent, $styles['font'], $styles['paragraph']); + if (strpos($target, '#') === 0) { + return $element->addLink(substr($target, 1), $node->textContent, $styles['font'], $styles['paragraph'], true); } + + return $element->addLink($target, $node->textContent, $styles['font'], $styles['paragraph']); } } diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index c9e4b4b162..9ec2249d24 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -453,7 +453,7 @@ public function testParseLink() $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:hyperlink')); $this->assertEquals('link text', $doc->getElement('/w:document/w:body/w:p/w:hyperlink/w:r/w:t')->nodeValue); - + $phpWord = new \PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); $section->addBookmark('bookmark'); @@ -464,7 +464,6 @@ public function testParseLink() $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:hyperlink')); $this->assertTrue($doc->getElement('/w:document/w:body/w:p/w:hyperlink')->hasAttribute('w:anchor')); $this->assertEquals('bookmark', $doc->getElement('/w:document/w:body/w:p/w:hyperlink')->getAttribute('w:anchor')); - } public function testParseMalformedStyleIsIgnored() From dd27f668e0143198348d0882ee632e33a1baa111 Mon Sep 17 00:00:00 2001 From: troosan Date: Sat, 14 Apr 2018 22:42:58 +0200 Subject: [PATCH 086/135] add line height test [ci skip] --- tests/PhpWord/Shared/HtmlTest.php | 5 +++++ tests/PhpWord/Writer/Word2007/ElementTest.php | 2 +- tests/PhpWord/Writer/Word2007/Style/FontTest.php | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index 9ec2249d24..f07b3f99a8 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -125,6 +125,7 @@ public function testParseLineHeight() $section = $phpWord->addSection(); Html::addHtml($section, '

        test

        '); Html::addHtml($section, '

        test

        '); + Html::addHtml($section, '

        test

        '); $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); $this->assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:pPr/w:spacing')); @@ -134,6 +135,10 @@ public function testParseLineHeight() $this->assertTrue($doc->elementExists('/w:document/w:body/w:p[2]/w:pPr/w:spacing')); $this->assertEquals(300, $doc->getElementAttribute('/w:document/w:body/w:p[2]/w:pPr/w:spacing', 'w:line')); $this->assertEquals(LineSpacingRule::EXACT, $doc->getElementAttribute('/w:document/w:body/w:p[2]/w:pPr/w:spacing', 'w:lineRule')); + + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p[3]/w:pPr/w:spacing')); + $this->assertEquals(Paragraph::LINE_HEIGHT * 1.2, $doc->getElementAttribute('/w:document/w:body/w:p[3]/w:pPr/w:spacing', 'w:line')); + $this->assertEquals(LineSpacingRule::AUTO, $doc->getElementAttribute('/w:document/w:body/w:p[3]/w:pPr/w:spacing', 'w:lineRule')); } /** diff --git a/tests/PhpWord/Writer/Word2007/ElementTest.php b/tests/PhpWord/Writer/Word2007/ElementTest.php index 979a4337ba..d365861a9a 100644 --- a/tests/PhpWord/Writer/Word2007/ElementTest.php +++ b/tests/PhpWord/Writer/Word2007/ElementTest.php @@ -256,7 +256,7 @@ public function testChartElements() { $phpWord = new PhpWord(); $section = $phpWord->addSection(); - $style = array('width' => 1000000, 'height' => 1000000); + $style = array('width' => 1000000, 'height' => 1000000, 'showAxisLabels' => true, 'showGridX' => true, 'showGridY' => true); $chartTypes = array('pie', 'doughnut', 'bar', 'line', 'area', 'scatter', 'radar'); $categories = array('A', 'B', 'C', 'D', 'E'); diff --git a/tests/PhpWord/Writer/Word2007/Style/FontTest.php b/tests/PhpWord/Writer/Word2007/Style/FontTest.php index c57f50ab54..ccfffbfb01 100644 --- a/tests/PhpWord/Writer/Word2007/Style/FontTest.php +++ b/tests/PhpWord/Writer/Word2007/Style/FontTest.php @@ -43,7 +43,7 @@ public function testFontRTL() $phpWord = new \PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); $textrun = $section->addTextRun(); - $textrun->addText('سلام این یک پاراگراف راست به چپ است', array('rtl' => true)); + $textrun->addText('سلام این یک پاراگراف راست به چپ است', array('rtl' => true, 'lang' => 'ar-DZ')); $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); $file = 'word/document.xml'; From 85e1e5c280b89b45104ad7c270a9c07cada8d718 Mon Sep 17 00:00:00 2001 From: troosan Date: Sat, 14 Apr 2018 23:21:02 +0200 Subject: [PATCH 087/135] fix warning --- src/PhpWord/ComplexType/TblWidth.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PhpWord/ComplexType/TblWidth.php b/src/PhpWord/ComplexType/TblWidth.php index 91dedc3ded..0d1a2419a7 100644 --- a/src/PhpWord/ComplexType/TblWidth.php +++ b/src/PhpWord/ComplexType/TblWidth.php @@ -31,8 +31,8 @@ final class TblWidth private $value; /** - * @param int $value If omitted, then its value shall be assumed to be 0. - * @param string $type If omitted, then its value shall be assumed to be dxa. + * @param int $value If omitted, then its value shall be assumed to be 0 + * @param string $type If omitted, then its value shall be assumed to be dxa */ public function __construct($value = 0, $type = TblWidthSimpleType::TWIP) { From c52c96d6573363f764d7bfba42be3ce998d1dc0e Mon Sep 17 00:00:00 2001 From: troosan Date: Tue, 17 Apr 2018 07:34:57 +0200 Subject: [PATCH 088/135] add support for STYLEREF field --- samples/Sample_27_Field.php | 5 +++++ src/PhpWord/Element/Field.php | 4 ++++ src/PhpWord/Writer/Word2007/Element/Field.php | 3 +++ tests/PhpWord/Writer/Word2007/ElementTest.php | 1 + 4 files changed, 13 insertions(+) diff --git a/samples/Sample_27_Field.php b/samples/Sample_27_Field.php index 9c37dffe91..4e7a5b2264 100644 --- a/samples/Sample_27_Field.php +++ b/samples/Sample_27_Field.php @@ -6,15 +6,20 @@ // New Word document echo date('H:i:s'), ' Create new PhpWord object', EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); +PhpOffice\PhpWord\Style::addTitleStyle(1, array('size' => 14)); // New section $section = $phpWord->addSection(); +$section->addTitle('This page demos fields'); // Add Field elements // See Element/Field.php for all options $section->addText('Date field:'); $section->addField('DATE', array('dateformat' => 'dddd d MMMM yyyy H:mm:ss'), array('PreserveFormat')); +$section->addText('Style Ref field:'); +$section->addField('STYLEREF', array('StyleIdentifier' => 'Heading 1')); + $section->addText('Page field:'); $section->addField('PAGE', array('format' => 'Arabic')); diff --git a/src/PhpWord/Element/Field.php b/src/PhpWord/Element/Field.php index 0e5e28ed6d..2efc6b0b9f 100644 --- a/src/PhpWord/Element/Field.php +++ b/src/PhpWord/Element/Field.php @@ -78,6 +78,10 @@ class Field extends AbstractElement 'properties' => array(), 'options' => array('PreserveFormat'), ), + 'STYLEREF' => array( + 'properties' => array('StyleIdentifier' => ''), + 'options' => array('PreserveFormat'), + ), ); /** diff --git a/src/PhpWord/Writer/Word2007/Element/Field.php b/src/PhpWord/Writer/Word2007/Element/Field.php index cf3fbd6606..e79dd24a90 100644 --- a/src/PhpWord/Writer/Word2007/Element/Field.php +++ b/src/PhpWord/Writer/Word2007/Element/Field.php @@ -177,6 +177,9 @@ private function buildPropertiesAndOptions(\PhpOffice\PhpWord\Element\Field $ele case 'macroname': $propertiesAndOptions .= $propval . ' '; break; + default: + $propertiesAndOptions .= '"' . $propval . '" '; + break; } } diff --git a/tests/PhpWord/Writer/Word2007/ElementTest.php b/tests/PhpWord/Writer/Word2007/ElementTest.php index d365861a9a..25c62eccea 100644 --- a/tests/PhpWord/Writer/Word2007/ElementTest.php +++ b/tests/PhpWord/Writer/Word2007/ElementTest.php @@ -288,6 +288,7 @@ public function testFieldElement() $section->addField('DATE', array(), array('LunarCalendar')); $section->addField('DATE', array(), array('SakaEraCalendar')); $section->addField('NUMPAGES', array('format' => 'roman', 'numformat' => '0,00'), array('SakaEraCalendar')); + $section->addField('STYLEREF', array('StyleIdentifier' => 'Heading 1')); $doc = TestHelperDOCX::getDocument($phpWord); $element = '/w:document/w:body/w:p/w:r/w:instrText'; From b147919a64d86dbdf878130c413c310e4c167200 Mon Sep 17 00:00:00 2001 From: troosan Date: Wed, 18 Apr 2018 22:34:53 +0200 Subject: [PATCH 089/135] write column width in ODT writer --- CHANGELOG.md | 1 + src/PhpWord/Element/Table.php | 24 +++++++ src/PhpWord/Style/Table.php | 27 ++++++++ src/PhpWord/Writer/ODText/Element/Table.php | 63 ++++++++++++++----- src/PhpWord/Writer/ODText/Part/Content.php | 1 + src/PhpWord/Writer/ODText/Style/Table.php | 13 ++++ src/PhpWord/Writer/Word2007/Element/Table.php | 16 +---- 7 files changed, 114 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb07fcc243..7a49f25e86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ v0.15.0 (?? ??? 2018) - Fix colspan and rowspan for tables in HTML Writer @mattbolt #1292 - Fix parsing of Heading and Title formating @troosan @gthomas2 #465 - Fix Dateformat typo, fix hours casing, add Month-Day-Year formats @ComputerTinker #591 +- Fix missing column with in ODText writer @potofcoffee #413 ### Changed - Remove zend-stdlib dependency @Trainmaster #1284 diff --git a/src/PhpWord/Element/Table.php b/src/PhpWord/Element/Table.php index 10c4db69ab..1610211961 100644 --- a/src/PhpWord/Element/Table.php +++ b/src/PhpWord/Element/Table.php @@ -149,4 +149,28 @@ public function countColumns() return $columnCount; } + + /** + * The first declared cell width for each column + * + * @return int[] + */ + public function findFirstDefinedCellWidths() + { + $cellWidths = array(); + if (is_array($this->rows)) { + foreach ($this->rows as $row) { + $cells = $row->getCells(); + if (count($cells) <= count($cellWidths)) { + continue; + } + $cellWidths = array(); + foreach ($cells as $cell) { + $cellWidths[] = $cell->getWidth(); + } + } + } + + return $cellWidths; + } } diff --git a/src/PhpWord/Style/Table.php b/src/PhpWord/Style/Table.php index feb028da2c..5d4a0150ee 100644 --- a/src/PhpWord/Style/Table.php +++ b/src/PhpWord/Style/Table.php @@ -159,6 +159,13 @@ class Table extends Border */ private $position; + /** + * The width of each column, computed based on the max cell width of each column + * + * @var int[] + */ + private $columnWidths; + /** * Create new table style * @@ -724,4 +731,24 @@ public function setPosition($value = null) return $this; } + + /** + * Get the columnWidths + * + * @return number[] + */ + public function getColumnWidths() + { + return $this->columnWidths; + } + + /** + * The column widths + * + * @param int[] $value + */ + public function setColumnWidths(array $value = null) + { + $this->columnWidths = $value; + } } diff --git a/src/PhpWord/Writer/ODText/Element/Table.php b/src/PhpWord/Writer/ODText/Element/Table.php index 8a21ee1b47..088330ae5f 100644 --- a/src/PhpWord/Writer/ODText/Element/Table.php +++ b/src/PhpWord/Writer/ODText/Element/Table.php @@ -17,6 +17,10 @@ namespace PhpOffice\PhpWord\Writer\ODText\Element; +use PhpOffice\Common\XMLWriter; +use PhpOffice\PhpWord\Element\Row as RowElement; +use PhpOffice\PhpWord\Element\Table as TableElement; + /** * Table element writer * @@ -36,32 +40,59 @@ public function write() } $rows = $element->getRows(); $rowCount = count($rows); - $colCount = $element->countColumns(); if ($rowCount > 0) { $xmlWriter->startElement('table:table'); $xmlWriter->writeAttribute('table:name', $element->getElementId()); $xmlWriter->writeAttribute('table:style', $element->getElementId()); - $xmlWriter->startElement('table:table-column'); - $xmlWriter->writeAttribute('table:number-columns-repeated', $colCount); - $xmlWriter->endElement(); // table:table-column + // Write columns + $this->writeColumns($xmlWriter, $element); + // Write rows foreach ($rows as $row) { - $xmlWriter->startElement('table:table-row'); - /** @var $row \PhpOffice\PhpWord\Element\Row Type hint */ - foreach ($row->getCells() as $cell) { - $xmlWriter->startElement('table:table-cell'); - $xmlWriter->writeAttribute('office:value-type', 'string'); - - $containerWriter = new Container($xmlWriter, $cell); - $containerWriter->write(); - - $xmlWriter->endElement(); // table:table-cell - } - $xmlWriter->endElement(); // table:table-row + $this->writeRow($xmlWriter, $row); } $xmlWriter->endElement(); // table:table } } + + /** + * Write column. + * + * @param \PhpOffice\Common\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Element\Table $element + */ + private function writeColumns(XMLWriter $xmlWriter, TableElement $element) + { + $colCount = $element->countColumns(); + + for ($i = 0; $i < $colCount; $i++) { + $xmlWriter->startElement('table:table-column'); + $xmlWriter->writeAttribute('table:style-name', $element->getElementId() . '.' . $i); + $xmlWriter->endElement(); + } + } + + /** + * Write row. + * + * @param \PhpOffice\Common\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Element\Row $row + */ + private function writeRow(XMLWriter $xmlWriter, RowElement $row) + { + $xmlWriter->startElement('table:table-row'); + /** @var $row \PhpOffice\PhpWord\Element\Row Type hint */ + foreach ($row->getCells() as $cell) { + $xmlWriter->startElement('table:table-cell'); + $xmlWriter->writeAttribute('office:value-type', 'string'); + + $containerWriter = new Container($xmlWriter, $cell); + $containerWriter->write(); + + $xmlWriter->endElement(); // table:table-cell + } + $xmlWriter->endElement(); // table:table-row + } } diff --git a/src/PhpWord/Writer/ODText/Part/Content.php b/src/PhpWord/Writer/ODText/Part/Content.php index a50eea7ba0..b705bb5e81 100644 --- a/src/PhpWord/Writer/ODText/Part/Content.php +++ b/src/PhpWord/Writer/ODText/Part/Content.php @@ -246,6 +246,7 @@ private function getContainerStyle($container, &$paragraphStyleCount, &$fontStyl $style = Style::getStyle($style); } $style->setStyleName($element->getElementId()); + $style->setColumnWidths($element->findFirstDefinedCellWidths()); $this->autoStyles['Table'][] = $style; } } diff --git a/src/PhpWord/Writer/ODText/Style/Table.php b/src/PhpWord/Writer/ODText/Style/Table.php index 249321cff8..f5a3c431d0 100644 --- a/src/PhpWord/Writer/ODText/Style/Table.php +++ b/src/PhpWord/Writer/ODText/Style/Table.php @@ -45,5 +45,18 @@ public function write() $xmlWriter->writeAttribute('table:align', 'center'); $xmlWriter->endElement(); // style:table-properties $xmlWriter->endElement(); // style:style + + $cellWidths = $style->getColumnWidths(); + + for ($i = 0; $i < count($cellWidths); $i++) { + $width = $cellWidths[$i]; + $xmlWriter->startElement('style:style'); + $xmlWriter->writeAttribute('style:name', $style->getStyleName() . '.' . $i); + $xmlWriter->writeAttribute('style:family', 'table-column'); + $xmlWriter->startElement('style:table-column-properties'); + $xmlWriter->writeAttribute('style:column-width', number_format($width * 0.0017638889, 2, '.', '') . 'cm'); + $xmlWriter->endElement(); // style:table-column-properties + $xmlWriter->endElement(); // style:style + } } } diff --git a/src/PhpWord/Writer/Word2007/Element/Table.php b/src/PhpWord/Writer/Word2007/Element/Table.php index 25a48ab2cc..c365b028ab 100644 --- a/src/PhpWord/Writer/Word2007/Element/Table.php +++ b/src/PhpWord/Writer/Word2007/Element/Table.php @@ -76,21 +76,7 @@ public function write() */ private function writeColumns(XMLWriter $xmlWriter, TableElement $element) { - $rows = $element->getRows(); - $rowCount = count($rows); - - $cellWidths = array(); - for ($i = 0; $i < $rowCount; $i++) { - $row = $rows[$i]; - $cells = $row->getCells(); - if (count($cells) <= count($cellWidths)) { - continue; - } - $cellWidths = array(); - foreach ($cells as $cell) { - $cellWidths[] = $cell->getWidth(); - } - } + $cellWidths = $element->findFirstDefinedCellWidths(); $xmlWriter->startElement('w:tblGrid'); foreach ($cellWidths as $width) { From 5ec2c8560efbcc7c0daa888f9025f6e5164ffbd8 Mon Sep 17 00:00:00 2001 From: troosan Date: Wed, 25 Apr 2018 22:33:48 +0200 Subject: [PATCH 090/135] do not push code coverage after build of develop branch [ci skip] --- .travis_shell_after_success.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis_shell_after_success.sh b/.travis_shell_after_success.sh index 1272852619..06feddaa12 100644 --- a/.travis_shell_after_success.sh +++ b/.travis_shell_after_success.sh @@ -5,7 +5,7 @@ echo "TRAVIS_REPO_SLUG: $TRAVIS_REPO_SLUG" echo "TRAVIS_PHP_VERSION: $TRAVIS_PHP_VERSION" echo "TRAVIS_PULL_REQUEST: $TRAVIS_PULL_REQUEST" -if [ "$TRAVIS_REPO_SLUG" == "PHPOffice/PHPWord" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_PHP_VERSION" == "5.6" ]; then +if [ "$TRAVIS_REPO_SLUG" == "PHPOffice/PHPWord" ] && [ "$TRAVIS_BRANCH" != "develop" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_PHP_VERSION" == "5.6" ]; then echo -e "Publishing PHPDoc...\n" From 94be56b0ec6fcbb43d8a48bae9e74d3d93c5beb7 Mon Sep 17 00:00:00 2001 From: troosan Date: Wed, 25 Apr 2018 23:57:07 +0200 Subject: [PATCH 091/135] fix parsing of link style --- samples/Sample_26_Html.php | 2 +- src/PhpWord/Shared/Html.php | 2 +- tests/PhpWord/Shared/HtmlTest.php | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/samples/Sample_26_Html.php b/samples/Sample_26_Html.php index d876380531..e1823c4352 100644 --- a/samples/Sample_26_Html.php +++ b/samples/Sample_26_Html.php @@ -11,7 +11,7 @@ $html .= '

        Some well-formed HTML snippet needs to be used

        '; $html .= '

        With for example some1 inline formatting1

        '; -$html .= '

        A link to Read the docs

        '; +$html .= '

        A link to Read the docs

        '; $html .= '

        היי, זה פסקה מימין לשמאל

        '; diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 7d8ee51f1d..cbdcecd537 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -721,7 +721,7 @@ private static function parseLink($node, $element, &$styles) break; } } - self::parseInlineStyle($node, $styles['font']); + $styles['font'] = self::parseInlineStyle($node, $styles['font']); if (strpos($target, '#') === 0) { return $element->addLink(substr($target, 1), $node->textContent, $styles['font'], $styles['paragraph'], true); diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index f07b3f99a8..b61418e01c 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -458,6 +458,8 @@ public function testParseLink() $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:hyperlink')); $this->assertEquals('link text', $doc->getElement('/w:document/w:body/w:p/w:hyperlink/w:r/w:t')->nodeValue); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:hyperlink/w:r/w:rPr/w:u')); + $this->assertEquals('single', $doc->getElementAttribute('/w:document/w:body/w:p/w:hyperlink/w:r/w:rPr/w:u', 'w:val')); $phpWord = new \PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); From 96a47ec0ae5a88f752de16226cc950bae2ea760c Mon Sep 17 00:00:00 2001 From: Christian Zosel Date: Thu, 26 Apr 2018 08:41:00 +0200 Subject: [PATCH 092/135] Drop GitHub pages First step to fix #1355 --- .travis.yml | 2 -- .travis_shell_after_success.sh | 39 ---------------------------------- 2 files changed, 41 deletions(-) delete mode 100644 .travis_shell_after_success.sh diff --git a/.travis.yml b/.travis.yml index 281c263098..52fa95801c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,7 +55,5 @@ script: - if [ -z "$COVERAGE" ]; then ./vendor/bin/phpdoc -q -d ./src -t ./build/docs --ignore "*/src/PhpWord/Shared/*/*" --template="responsive-twig" ; fi after_script: - ## PHPDocumentor - - bash .travis_shell_after_success.sh ## Scrutinizer - if [ -n "$COVERAGE" ]; then wget https://scrutinizer-ci.com/ocular.phar && php ocular.phar code-coverage:upload --format=php-clover build/logs/clover.xml ; fi diff --git a/.travis_shell_after_success.sh b/.travis_shell_after_success.sh deleted file mode 100644 index 06feddaa12..0000000000 --- a/.travis_shell_after_success.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash - -echo "--DEBUG--" -echo "TRAVIS_REPO_SLUG: $TRAVIS_REPO_SLUG" -echo "TRAVIS_PHP_VERSION: $TRAVIS_PHP_VERSION" -echo "TRAVIS_PULL_REQUEST: $TRAVIS_PULL_REQUEST" - -if [ "$TRAVIS_REPO_SLUG" == "PHPOffice/PHPWord" ] && [ "$TRAVIS_BRANCH" != "develop" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_PHP_VERSION" == "5.6" ]; then - - echo -e "Publishing PHPDoc...\n" - - cp -R build/docs $HOME/docs-latest - cp -R build/coverage $HOME/coverage-latest - - cd $HOME - git config --global user.email "travis@travis-ci.org" - git config --global user.name "travis-ci" - git clone --quiet --branch=gh-pages https://${GH_TOKEN}@github.com/PHPOffice/PHPWord gh-pages > /dev/null - - cd gh-pages - echo "--DEBUG : Suppression" - git rm -rf ./docs/$TRAVIS_BRANCH - - echo "--DEBUG : Dossier" - mkdir -p docs/$TRAVIS_BRANCH - mkdir -p coverage/$TRAVIS_BRANCH - - echo "--DEBUG : Copie" - cp -Rf $HOME/docs-latest/* ./docs/$TRAVIS_BRANCH/ - cp -Rf $HOME/coverage-latest/* ./coverage/$TRAVIS_BRANCH/ - - echo "--DEBUG : Git" - git add -f . - git commit -m "PHPDocumentor (Travis Build: $TRAVIS_BUILD_NUMBER - Branch: $TRAVIS_BRANCH)" - git push -fq origin gh-pages > /dev/null - - echo -e "Published PHPDoc to gh-pages.\n" - -fi From 65b0f062ad05836d939a76b3f62fdae0e0895e0c Mon Sep 17 00:00:00 2001 From: JAEK-S Date: Fri, 11 May 2018 14:50:19 -0600 Subject: [PATCH 093/135] New features when creating charts (#1332) * add stacked bar and column charts * add chart colors feature * adding preliminary chart axis title functionality to XMLwriter * added percent_stacked to available types array * Make tick mark and tick label positions configurable * scrutinizer fixes * update changelog --- CHANGELOG.md | 1 + samples/Sample_32_Chart.php | 4 +- src/PhpWord/Element/Chart.php | 16 +- src/PhpWord/Style/Chart.php | 212 +++++++++++++++++++++ src/PhpWord/Writer/Word2007/Part/Chart.php | 131 +++++++++++-- tests/PhpWord/Style/ChartTest.php | 188 ++++++++++++++++++ 6 files changed, 531 insertions(+), 21 deletions(-) create mode 100644 tests/PhpWord/Style/ChartTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b5d77675f..fdb2b22b87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ v0.15.0 (?? ??? 2018) - Added the ability to enable gridlines and axislabels on charts @FrankMeyer #576 - Add support for table indent (tblInd) @Trainmaster #1343 - Added parsing of internal links in HTML reader @lalop #1336 +- Several improvements to charts @JAEK-S #1332 ### Fixed - Fix reading of docx default style - @troosan #1238 diff --git a/samples/Sample_32_Chart.php b/samples/Sample_32_Chart.php index 87d6f3e38f..c24a6f8e37 100644 --- a/samples/Sample_32_Chart.php +++ b/samples/Sample_32_Chart.php @@ -16,8 +16,8 @@ $section->addTitle('2D charts', 1); $section = $phpWord->addSection(array('colsNum' => 2, 'breakType' => 'continuous')); -$chartTypes = array('pie', 'doughnut', 'bar', 'column', 'line', 'area', 'scatter', 'radar'); -$twoSeries = array('bar', 'column', 'line', 'area', 'scatter', 'radar'); +$chartTypes = array('pie', 'doughnut', 'bar', 'column', 'line', 'area', 'scatter', 'radar', 'stacked_bar', 'percent_stacked_bar', 'stacked_column', 'percent_stacked_column'); +$twoSeries = array('bar', 'column', 'line', 'area', 'scatter', 'radar', 'stacked_bar', 'percent_stacked_bar', 'stacked_column', 'percent_stacked_column'); $threeSeries = array('bar', 'line'); $categories = array('A', 'B', 'C', 'D', 'E'); $series1 = array(1, 3, 2, 5, 4); diff --git a/src/PhpWord/Element/Chart.php b/src/PhpWord/Element/Chart.php index 755f45e160..92152c877d 100644 --- a/src/PhpWord/Element/Chart.php +++ b/src/PhpWord/Element/Chart.php @@ -61,11 +61,12 @@ class Chart extends AbstractElement * @param array $categories * @param array $values * @param array $style + * @param null|mixed $seriesName */ - public function __construct($type, $categories, $values, $style = null) + public function __construct($type, $categories, $values, $style = null, $seriesName = null) { $this->setType($type); - $this->addSeries($categories, $values); + $this->addSeries($categories, $values, $seriesName); $this->style = $this->setNewStyle(new ChartStyle(), $style, true); } @@ -86,7 +87,7 @@ public function getType() */ public function setType($value) { - $enum = array('pie', 'doughnut', 'line', 'bar', 'column', 'area', 'radar', 'scatter'); + $enum = array('pie', 'doughnut', 'line', 'bar', 'stacked_bar', 'percent_stacked_bar', 'column', 'stacked_column', 'percent_stacked_column', 'area', 'radar', 'scatter'); $this->type = $this->setEnumVal($value, $enum, 'pie'); } @@ -95,10 +96,15 @@ public function setType($value) * * @param array $categories * @param array $values + * @param null|mixed $name */ - public function addSeries($categories, $values) + public function addSeries($categories, $values, $name = null) { - $this->series[] = array('categories' => $categories, 'values' => $values); + $this->series[] = array( + 'categories' => $categories, + 'values' => $values, + 'name' => $name, + ); } /** diff --git a/src/PhpWord/Style/Chart.php b/src/PhpWord/Style/Chart.php index 041736beb4..5b02e63631 100644 --- a/src/PhpWord/Style/Chart.php +++ b/src/PhpWord/Style/Chart.php @@ -46,6 +46,60 @@ class Chart extends AbstractStyle private $is3d = false; /** + * A list of colors to use in the chart + * + * @var array + */ + private $colors = array(); + + /** + * A list of display options for data labels + * + * @var array + */ + private $dataLabelOptions = array( + 'showVal' => true, // value + 'showCatName' => true, // category name + 'showLegendKey' => false, //show the cart legend + 'showSerName' => false, // series name + 'showPercent' => false, + 'showLeaderLines' => false, + 'showBubbleSize' => false, + ); + + /** + * A string that tells the writer where to write chart labels or to skip + * "nextTo" - sets labels next to the axis (bar graphs on the left) (default) + * "low" - labels on the left side of the graph + * "high" - labels on the right side of the graph + * + * @var string + */ + private $categoryLabelPosition = 'nextTo'; + + /** + * A string that tells the writer where to write chart labels or to skip + * "nextTo" - sets labels next to the axis (bar graphs on the bottom) (default) + * "low" - labels are below the graph + * "high" - labels above the graph + * + * @var string + */ + private $valueLabelPosition = 'nextTo'; + + /** + * @var string + */ + private $categoryAxisTitle; + + /** + * @var string + */ + private $valueAxisTitle; + + private $majorTickMarkPos = 'none'; + + /* * Show labels for axis * * @var bool @@ -146,6 +200,28 @@ public function set3d($value = true) } /** + * Get the list of colors to use in a chart. + * + * @return array + */ + public function getColors() + { + return $this->colors; + } + + /** + * Set the colors to use in a chart. + * + * @param array $value a list of colors to use in the chart + */ + public function setColors($value = array()) + { + $this->colors = $value; + + return $this; + } + + /* * Show labels for axis * * @return bool @@ -169,6 +245,31 @@ public function setShowAxisLabels($value = true) } /** + * get the list of options for data labels + * + * @return array + */ + public function getDataLabelOptions() + { + return $this->dataLabelOptions; + } + + /** + * Set values for data label options. + * This will only change values for options defined in $this->dataLabelOptions, and cannot create new ones. + * + * @param array $values [description] + */ + public function setDataLabelOptions($values = array()) + { + foreach (array_keys($this->dataLabelOptions) as $option) { + if (isset($values[$option])) { + $this->dataLabelOptions[$option] = $this->setBoolVal($values[$option], $this->dataLabelOptions[$option]); + } + } + } + + /* * Show Gridlines for Y-Axis * * @return bool @@ -192,6 +293,117 @@ public function setShowGridY($value = true) } /** + * Get the categoryLabelPosition setting + * + * @return string + */ + public function getCategoryLabelPosition() + { + return $this->categoryLabelPosition; + } + + /** + * Set the categoryLabelPosition setting + * "none" - skips writing labels + * "nextTo" - sets labels next to the (bar graphs on the left) + * "low" - labels on the left side of the graph + * "high" - labels on the right side of the graph + * + * @param mixed $labelPosition + * @return self + */ + public function setCategoryLabelPosition($labelPosition) + { + $enum = array('nextTo', 'low', 'high'); + $this->categoryLabelPosition = $this->setEnumVal($labelPosition, $enum, $this->categoryLabelPosition); + + return $this; + } + + /** + * Get the valueAxisLabelPosition setting + * + * @return string + */ + public function getValueLabelPosition() + { + return $this->valueLabelPosition; + } + + /** + * Set the valueLabelPosition setting + * "none" - skips writing labels + * "nextTo" - sets labels next to the value + * "low" - sets labels are below the graph + * "high" - sets labels above the graph + * + * @param string + * @param mixed $labelPosition + */ + public function setValueLabelPosition($labelPosition) + { + $enum = array('nextTo', 'low', 'high'); + $this->valueLabelPosition = $this->setEnumVal($labelPosition, $enum, $this->valueLabelPosition); + + return $this; + } + + /** + * Get the categoryAxisTitle + * @return string + */ + public function getCategoryAxisTitle() + { + return $this->categoryAxisTitle; + } + + /** + * Set the title that appears on the category side of the chart + * @param string $axisTitle + */ + public function setCategoryAxisTitle($axisTitle) + { + $this->categoryAxisTitle = $axisTitle; + + return $this; + } + + /** + * Get the valueAxisTitle + * @return string + */ + public function getValueAxisTitle() + { + return $this->valueAxisTitle; + } + + /** + * Set the title that appears on the value side of the chart + * @param string $axisTitle + */ + public function setValueAxisTitle($axisTitle) + { + $this->valueAxisTitle = $axisTitle; + + return $this; + } + + public function getMajorTickPosition() + { + return $this->majorTickMarkPos; + } + + /** + * set the position for major tick marks + * @param string $position [description] + */ + public function setMajorTickPosition($position) + { + $enum = array('in', 'out', 'cross', 'none'); + $this->majorTickMarkPos = $this->setEnumVal($position, $enum, $this->majorTickMarkPos); + } + + /* * Show Gridlines for X-Axis * * @return bool diff --git a/src/PhpWord/Writer/Word2007/Part/Chart.php b/src/PhpWord/Writer/Word2007/Part/Chart.php index 2aeccca02d..17c1fd54ac 100644 --- a/src/PhpWord/Writer/Word2007/Part/Chart.php +++ b/src/PhpWord/Writer/Word2007/Part/Chart.php @@ -41,14 +41,18 @@ class Chart extends AbstractPart * @var array */ private $types = array( - 'pie' => array('type' => 'pie', 'colors' => 1), - 'doughnut' => array('type' => 'doughnut', 'colors' => 1, 'hole' => 75, 'no3d' => true), - 'bar' => array('type' => 'bar', 'colors' => 0, 'axes' => true, 'bar' => 'bar'), - 'column' => array('type' => 'bar', 'colors' => 0, 'axes' => true, 'bar' => 'col'), - 'line' => array('type' => 'line', 'colors' => 0, 'axes' => true), - 'area' => array('type' => 'area', 'colors' => 0, 'axes' => true), - 'radar' => array('type' => 'radar', 'colors' => 0, 'axes' => true, 'radar' => 'standard', 'no3d' => true), - 'scatter' => array('type' => 'scatter', 'colors' => 0, 'axes' => true, 'scatter' => 'marker', 'no3d' => true), + 'pie' => array('type' => 'pie', 'colors' => 1), + 'doughnut' => array('type' => 'doughnut', 'colors' => 1, 'hole' => 75, 'no3d' => true), + 'bar' => array('type' => 'bar', 'colors' => 0, 'axes' => true, 'bar' => 'bar', 'grouping' => 'clustered'), + 'stacked_bar' => array('type' => 'bar', 'colors' => 0, 'axes' => true, 'bar' => 'bar', 'grouping' => 'stacked'), + 'percent_stacked_bar' => array('type' => 'bar', 'colors' => 0, 'axes' => true, 'bar' => 'bar', 'grouping' => 'percentStacked'), + 'column' => array('type' => 'bar', 'colors' => 0, 'axes' => true, 'bar' => 'col', 'grouping' => 'clustered'), + 'stacked_column' => array('type' => 'bar', 'colors' => 0, 'axes' => true, 'bar' => 'col', 'grouping' => 'stacked'), + 'percent_stacked_column' => array('type' => 'bar', 'colors' => 0, 'axes' => true, 'bar' => 'col', 'grouping' => 'percentStacked'), + 'line' => array('type' => 'line', 'colors' => 0, 'axes' => true), + 'area' => array('type' => 'area', 'colors' => 0, 'axes' => true), + 'radar' => array('type' => 'radar', 'colors' => 0, 'axes' => true, 'radar' => 'standard', 'no3d' => true), + 'scatter' => array('type' => 'scatter', 'colors' => 0, 'axes' => true, 'scatter' => 'marker', 'no3d' => true), ); /** @@ -145,7 +149,7 @@ private function writePlotArea(XMLWriter $xmlWriter) } if (isset($this->options['bar'])) { $xmlWriter->writeElementBlock('c:barDir', 'val', $this->options['bar']); // bar|col - $xmlWriter->writeElementBlock('c:grouping', 'val', 'clustered'); // 3d; standard = percentStacked + $xmlWriter->writeElementBlock('c:grouping', 'val', $this->options['grouping']); // 3d; standard = percentStacked } if (isset($this->options['radar'])) { $xmlWriter->writeElementBlock('c:radarStyle', 'val', $this->options['radar']); @@ -157,6 +161,8 @@ private function writePlotArea(XMLWriter $xmlWriter) // Series $this->writeSeries($xmlWriter, isset($this->options['scatter'])); + $xmlWriter->writeElementBlock('c:overlap', 'val', '100'); + // Axes if (isset($this->options['axes'])) { $xmlWriter->writeElementBlock('c:axId', 'val', 1); @@ -183,6 +189,8 @@ private function writePlotArea(XMLWriter $xmlWriter) private function writeSeries(XMLWriter $xmlWriter, $scatter = false) { $series = $this->element->getSeries(); + $style = $this->element->getStyle(); + $colors = $style->getColors(); $index = 0; foreach ($series as $seriesItem) { @@ -194,6 +202,32 @@ private function writeSeries(XMLWriter $xmlWriter, $scatter = false) $xmlWriter->writeElementBlock('c:idx', 'val', $index); $xmlWriter->writeElementBlock('c:order', 'val', $index); + if (!is_null($seriesItem['name']) && $seriesItem['name'] != '') { + $xmlWriter->startElement('c:tx'); + $xmlWriter->startElement('c:strRef'); + $xmlWriter->startElement('c:strCache'); + $xmlWriter->writeElementBlock('c:ptCount', 'val', 1); + $xmlWriter->startElement('c:pt'); + $xmlWriter->writeAttribute('idx', 0); + $xmlWriter->startElement('c:v'); + $xmlWriter->writeRaw($seriesItem['name']); + $xmlWriter->endElement(); // c:v + $xmlWriter->endElement(); // c:pt + $xmlWriter->endElement(); // c:strCache + $xmlWriter->endElement(); // c:strRef + $xmlWriter->endElement(); // c:tx + } + + // The c:dLbls was added to make word charts look more like the reports in SurveyGizmo + // This section needs to be made configurable before a pull request is made + $xmlWriter->startElement('c:dLbls'); + + foreach ($style->getDataLabelOptions() as $option => $val) { + $xmlWriter->writeElementBlock("c:{$option}", 'val', (int) $val); + } + + $xmlWriter->endElement(); // c:dLbls + if (isset($this->options['scatter'])) { $this->writeShape($xmlWriter); } @@ -204,6 +238,26 @@ private function writeSeries(XMLWriter $xmlWriter, $scatter = false) } else { $this->writeSeriesItem($xmlWriter, 'cat', $categories); $this->writeSeriesItem($xmlWriter, 'val', $values); + + // setting the chart colors was taken from https://github.com/PHPOffice/PHPWord/issues/494 + if (is_array($colors) && count($colors)) { + // This is a workaround to make each series in a stack chart use a different color + if ($this->options['type'] == 'bar' && stristr($this->options['grouping'], 'stacked')) { + array_shift($colors); + } + $colorIndex = 0; + foreach ($colors as $color) { + $xmlWriter->startElement('c:dPt'); + $xmlWriter->writeElementBlock('c:idx', 'val', $colorIndex); + $xmlWriter->startElement('c:spPr'); + $xmlWriter->startElement('a:solidFill'); + $xmlWriter->writeElementBlock('a:srgbClr', 'val', $color); + $xmlWriter->endElement(); // a:solidFill + $xmlWriter->endElement(); // c:spPr + $xmlWriter->endElement(); // c:dPt + $colorIndex++; + } + } } $xmlWriter->endElement(); // c:ser @@ -230,14 +284,19 @@ private function writeSeriesItem(XMLWriter $xmlWriter, $type, $values) $xmlWriter->startElement($itemType); $xmlWriter->startElement($itemLit); + $xmlWriter->writeElementBlock('c:ptCount', 'val', count($values)); $index = 0; foreach ($values as $value) { $xmlWriter->startElement('c:pt'); $xmlWriter->writeAttribute('idx', $index); - $xmlWriter->startElement('c:v'); - $xmlWriter->text($value); - $xmlWriter->endElement(); // c:v + if (\PhpOffice\PhpWord\Settings::isOutputEscapingEnabled()) { + $xmlWriter->writeElement('c:v', $value); + } else { + $xmlWriter->startElement('c:v'); + $xmlWriter->writeRaw($value); + $xmlWriter->endElement(); // c:v + } $xmlWriter->endElement(); // c:pt $index++; } @@ -266,15 +325,33 @@ private function writeAxis(XMLWriter $xmlWriter, $type) $xmlWriter->writeElementBlock('c:axId', 'val', $axisId); $xmlWriter->writeElementBlock('c:axPos', 'val', $axisPos); + + $categoryAxisTitle = $style->getCategoryAxisTitle(); + $valueAxisTitle = $style->getValueAxisTitle(); + + if ($axisType == 'c:catAx') { + if (isset($categoryAxisTitle)) { + $this->writeAxisTitle($xmlWriter, $categoryAxisTitle); + } + } elseif ($axisType == 'c:valAx') { + if (isset($valueAxisTitle)) { + $this->writeAxisTitle($xmlWriter, $valueAxisTitle); + } + } + $xmlWriter->writeElementBlock('c:crossAx', 'val', $axisCross); $xmlWriter->writeElementBlock('c:auto', 'val', 1); if (isset($this->options['axes'])) { $xmlWriter->writeElementBlock('c:delete', 'val', 0); - $xmlWriter->writeElementBlock('c:majorTickMark', 'val', 'none'); + $xmlWriter->writeElementBlock('c:majorTickMark', 'val', $style->getMajorTickPosition()); $xmlWriter->writeElementBlock('c:minorTickMark', 'val', 'none'); if ($style->showAxisLabels()) { - $xmlWriter->writeElementBlock('c:tickLblPos', 'val', 'nextTo'); + if ($axisType == 'c:catAx') { + $xmlWriter->writeElementBlock('c:tickLblPos', 'val', $style->getCategoryLabelPosition()); + } else { + $xmlWriter->writeElementBlock('c:tickLblPos', 'val', $style->getValueLabelPosition()); + } } else { $xmlWriter->writeElementBlock('c:tickLblPos', 'val', 'none'); } @@ -312,4 +389,30 @@ private function writeShape(XMLWriter $xmlWriter, $line = false) $xmlWriter->endElement(); // a:ln $xmlWriter->endElement(); // c:spPr } + + private function writeAxisTitle(XMLWriter $xmlWriter, $title) + { + $xmlWriter->startElement('c:title'); //start c:title + $xmlWriter->startElement('c:tx'); //start c:tx + $xmlWriter->startElement('c:rich'); // start c:rich + $xmlWriter->writeElement('a:bodyPr'); + $xmlWriter->writeElement('a:lstStyle'); + $xmlWriter->startElement('a:p'); + $xmlWriter->startElement('a:pPr'); + $xmlWriter->writeElement('a:defRPr'); + $xmlWriter->endElement(); // end a:pPr + $xmlWriter->startElement('a:r'); + $xmlWriter->writeElementBlock('a:rPr', 'lang', 'en-US'); + + $xmlWriter->startElement('a:t'); + $xmlWriter->writeRaw($title); + $xmlWriter->endElement(); //end a:t + + $xmlWriter->endElement(); // end a:r + $xmlWriter->endElement(); //end a:p + $xmlWriter->endElement(); //end c:rich + $xmlWriter->endElement(); // end c:tx + $xmlWriter->writeElementBlock('c:overlay', 'val', '0'); + $xmlWriter->endElement(); // end c:title + } } diff --git a/tests/PhpWord/Style/ChartTest.php b/tests/PhpWord/Style/ChartTest.php new file mode 100644 index 0000000000..9929a8f5a7 --- /dev/null +++ b/tests/PhpWord/Style/ChartTest.php @@ -0,0 +1,188 @@ +assertEquals($chart->getWidth(), 1000000); + + $chart->setWidth(200); + + $this->assertEquals($chart->getWidth(), 200); + } + + /** + * Testing getter and setter for chart height + */ + public function testSetGetHeight() + { + $chart = new Chart(); + + $this->assertEquals($chart->getHeight(), 1000000); + + $chart->setHeight(200); + + $this->assertEquals($chart->getHeight(), 200); + } + + /** + * Testing getter and setter for is3d + */ + public function testSetIs3d() + { + $chart = new Chart(); + + $this->assertEquals($chart->is3d(), false); + + $chart->set3d(true); + + $this->assertEquals($chart->is3d(), true); + } + + /** + * Testing getter and setter for chart colors + */ + public function testSetGetColors() + { + $chart = new Chart(); + + $this->assertInternalType('array', $chart->getColors()); + + $this->assertEquals(count($chart->getColors()), 0); + + $chart->setColors(array('FFFFFFFF', 'FF000000', 'FFFF0000')); + + $this->assertEquals($chart->getColors(), array('FFFFFFFF', 'FF000000', 'FFFF0000')); + } + + /** + * Testing getter and setter for dataLabelOptions + */ + public function testSetGetDataLabelOptions() + { + $chart = new Chart(); + + $originalDataLabelOptions = array( + 'showVal' => true, + 'showCatName' => true, + 'showLegendKey' => false, + 'showSerName' => false, + 'showPercent' => false, + 'showLeaderLines' => false, + 'showBubbleSize' => false, + ); + + $this->assertEquals($chart->getDataLabelOptions(), $originalDataLabelOptions); + + $changedDataLabelOptions = array( + 'showVal' => false, + 'showCatName' => false, + 'showLegendKey' => true, + 'showSerName' => true, + 'showPercent' => true, + 'showLeaderLines' => true, + 'showBubbleSize' => true, + ); + + $chart->setDataLabelOptions( + array( + 'showVal' => false, + 'showCatName' => false, + 'showLegendKey' => true, + 'showSerName' => true, + 'showPercent' => true, + 'showLeaderLines' => true, + 'showBubbleSize' => true, + ) + ); + $this->assertEquals($chart->getDataLabelOptions(), $changedDataLabelOptions); + } + + /** + * Testing categoryLabelPosition getter and setter + */ + public function testSetGetCategoryLabelPosition() + { + $chart = new Chart(); + + $this->assertEquals($chart->getCategoryLabelPosition(), 'nextTo'); + + $chart->setCategoryLabelPosition('high'); + + $this->assertEquals($chart->getCategoryLabelPosition(), 'high'); + } + + /** + * Testing valueLabelPosition getter and setter + */ + public function testSetGetValueLabelPosition() + { + $chart = new Chart(); + + $this->assertEquals($chart->getValueLabelPosition(), 'nextTo'); + + $chart->setValueLabelPosition('low'); + + $this->assertEquals($chart->getValueLabelPosition(), 'low'); + } + + /** + * Testing categoryAxisTitle getter and setter + */ + public function testSetGetCategoryAxisTitle() + { + $chart = new Chart(); + + $chart->getCategoryAxisTitle(); + + $this->assertEquals($chart->getCategoryAxisTitle(), null); + + $chart->setCategoryAxisTitle('Test Category Axis Title'); + + $this->assertEquals($chart->getCategoryAxisTitle(), 'Test Category Axis Title'); + } + + /** + * Testing valueAxisTitle getter and setter + */ + public function testSetGetValueAxisTitle() + { + $chart = new Chart(); + + $chart->getValueAxisTitle(); + + $this->assertEquals($chart->getValueAxisTitle(), null); + + $chart->setValueAxisTitle('Test Value Axis Title'); + + $this->assertEquals($chart->getValueAxisTitle(), 'Test Value Axis Title'); + } +} From e47ce1b4fc493ecfa7d5b5cd60c425d54cd78a3b Mon Sep 17 00:00:00 2001 From: Christian Zosel Date: Sat, 19 May 2018 12:39:30 +0200 Subject: [PATCH 094/135] Coveralls integration --- .travis.yml | 6 +++--- composer.json | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 52fa95801c..d79a7dce27 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,6 +54,6 @@ script: ## PHPDocumentor - if [ -z "$COVERAGE" ]; then ./vendor/bin/phpdoc -q -d ./src -t ./build/docs --ignore "*/src/PhpWord/Shared/*/*" --template="responsive-twig" ; fi -after_script: - ## Scrutinizer - - if [ -n "$COVERAGE" ]; then wget https://scrutinizer-ci.com/ocular.phar && php ocular.phar code-coverage:upload --format=php-clover build/logs/clover.xml ; fi +after_success: + ## Coveralls + - if [ -z "$COVERAGE" ]; then travis_retry php vendor/bin/php-coveralls -v ; fi diff --git a/composer.json b/composer.json index 742e4bc8b4..e4d5927e5f 100644 --- a/composer.json +++ b/composer.json @@ -61,7 +61,8 @@ "php": "^5.3.3 || ^7.0", "ext-xml": "*", "zendframework/zend-escaper": "^2.2", - "phpoffice/common": "^0.2" + "phpoffice/common": "^0.2", + "php-coveralls/php-coveralls": "1.1.0" }, "require-dev": { "phpunit/phpunit": "^4.8.36 || ^5.0", From 453ddf078b16f996900317e8b5fc4294d71b09f0 Mon Sep 17 00:00:00 2001 From: troosan Date: Sun, 20 May 2018 14:37:59 +0200 Subject: [PATCH 095/135] Do not try to read document protection if not present --- src/PhpWord/Reader/Word2007/AbstractPart.php | 2 ++ src/PhpWord/Reader/Word2007/Settings.php | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 48a84ff2db..6cdf2b3a21 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -588,6 +588,8 @@ private function findPossibleAttribute(XMLReader $xmlReader, \DOMElement $node, return $possibleAttribute; } } + + return null; } return $attributes; diff --git a/src/PhpWord/Reader/Word2007/Settings.php b/src/PhpWord/Reader/Word2007/Settings.php index 5cfe5453c9..dbf3462335 100644 --- a/src/PhpWord/Reader/Word2007/Settings.php +++ b/src/PhpWord/Reader/Word2007/Settings.php @@ -109,7 +109,9 @@ protected function setDocumentProtection(XMLReader $xmlReader, PhpWord $phpWord, $documentProtection = $phpWord->getSettings()->getDocumentProtection(); $edit = $xmlReader->getAttribute('w:edit', $node); - $documentProtection->setEditing($edit); + if ($edit !== null) { + $documentProtection->setEditing($edit); + } } /** From 2480103b49c937da2c36a3573e5ab61f9469d8e6 Mon Sep 17 00:00:00 2001 From: troosan Date: Sun, 20 May 2018 17:13:04 +0200 Subject: [PATCH 096/135] run coveralls when running build with code coverage --- .travis.yml | 2 +- composer.json | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index d79a7dce27..bd85b2d77e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -56,4 +56,4 @@ script: after_success: ## Coveralls - - if [ -z "$COVERAGE" ]; then travis_retry php vendor/bin/php-coveralls -v ; fi + - if [ -n "$COVERAGE" ]; then travis_retry php vendor/bin/php-coveralls -v ; fi diff --git a/composer.json b/composer.json index e4d5927e5f..c29e901a38 100644 --- a/composer.json +++ b/composer.json @@ -61,8 +61,7 @@ "php": "^5.3.3 || ^7.0", "ext-xml": "*", "zendframework/zend-escaper": "^2.2", - "phpoffice/common": "^0.2", - "php-coveralls/php-coveralls": "1.1.0" + "phpoffice/common": "^0.2" }, "require-dev": { "phpunit/phpunit": "^4.8.36 || ^5.0", @@ -73,7 +72,8 @@ "phploc/phploc": "2.* || 3.* || 4.*", "dompdf/dompdf":"0.8.*", "tecnickcom/tcpdf": "6.*", - "mpdf/mpdf": "5.* || 6.* || 7.*" + "mpdf/mpdf": "5.* || 6.* || 7.*", + "php-coveralls/php-coveralls": "1.1.0 || ^2.0" }, "suggest": { "ext-zip": "Allows writing OOXML and ODF", From 254064150d1515768ab576085ff0feda5f00d9c7 Mon Sep 17 00:00:00 2001 From: troosan Date: Sun, 20 May 2018 20:59:34 +0200 Subject: [PATCH 097/135] disable external code coverage --- .scrutinizer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.scrutinizer.yml b/.scrutinizer.yml index 291a6d60cd..2b395afd26 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -19,7 +19,7 @@ tools: config: ruleset: phpmd.xml.dist external_code_coverage: - enabled: true + enabled: false timeout: 1200 php_cpd: true # php_sim: # Temporarily disabled to allow focus on things other than duplicates From 0b27bb927dc1af20510b0aa55e54ae74f1060692 Mon Sep 17 00:00:00 2001 From: troosan Date: Sun, 20 May 2018 22:08:53 +0200 Subject: [PATCH 098/135] update changelog [ci skip] --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b5d77675f..69f0c811d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,8 @@ v0.15.0 (?? ??? 2018) - Remove zend-stdlib dependency @Trainmaster #1284 - The default unit for `\PhpOffice\PhpWord\Style\Image` changed from `px` to `pt`. +### Miscelaneous +- Drop GitHub pages, switch to coveralls for code coverage analysis @czosel #1360 v0.14.0 (29 Dec 2017) ---------------------- From e6501eb9ff75d6de13768507d531c2327bae0e97 Mon Sep 17 00:00:00 2001 From: troosan Date: Sun, 20 May 2018 23:45:03 +0200 Subject: [PATCH 099/135] Update coverage badge [skip ci] [skip Scrutinizer] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 59fc3c44a9..7531a6bc11 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Latest Stable Version](https://poser.pugx.org/phpoffice/phpword/v/stable.png)](https://packagist.org/packages/phpoffice/phpword) [![Build Status](https://travis-ci.org/PHPOffice/PHPWord.svg?branch=master)](https://travis-ci.org/PHPOffice/PHPWord) [![Code Quality](https://scrutinizer-ci.com/g/PHPOffice/PHPWord/badges/quality-score.png?s=b5997ce59ac2816b4514f3a38de9900f6d492c1d)](https://scrutinizer-ci.com/g/PHPOffice/PHPWord/) -[![Code Coverage](https://scrutinizer-ci.com/g/PHPOffice/PHPWord/badges/coverage.png?s=742a98745725c562955440edc8d2c39d7ff5ae25)](https://scrutinizer-ci.com/g/PHPOffice/PHPWord/) +[![Coverage Status](https://coveralls.io/repos/github/PHPOffice/PHPWord/badge.svg?branch=develop)](https://coveralls.io/github/PHPOffice/PHPWord?branch=develop) [![Total Downloads](https://poser.pugx.org/phpoffice/phpword/downloads.png)](https://packagist.org/packages/phpoffice/phpword) [![License](https://poser.pugx.org/phpoffice/phpword/license.png)](https://packagist.org/packages/phpoffice/phpword) [![Join the chat at https://gitter.im/PHPOffice/PHPWord](https://img.shields.io/badge/GITTER-join%20chat-green.svg)](https://gitter.im/PHPOffice/PHPWord) From 90d4d30dd327d19aed30293e5ebebe8cd657ea2c Mon Sep 17 00:00:00 2001 From: woutersioen Date: Wed, 23 May 2018 09:18:24 +0200 Subject: [PATCH 100/135] Fix calls to the getEndingNotes method in the samples This call requires both an array of writes and the filename, which was missing in both method calls. --- samples/Sample_07_TemplateCloneRow.php | 2 +- samples/Sample_23_TemplateBlock.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/Sample_07_TemplateCloneRow.php b/samples/Sample_07_TemplateCloneRow.php index e845362c60..81253d0a65 100644 --- a/samples/Sample_07_TemplateCloneRow.php +++ b/samples/Sample_07_TemplateCloneRow.php @@ -56,7 +56,7 @@ echo date('H:i:s'), ' Saving the result document...', EOL; $templateProcessor->saveAs('results/Sample_07_TemplateCloneRow.docx'); -echo getEndingNotes(array('Word2007' => 'docx')); +echo getEndingNotes(array('Word2007' => 'docx'), 'results/Sample_07_TemplateCloneRow.docx'); if (!CLI) { include_once 'Sample_Footer.php'; } diff --git a/samples/Sample_23_TemplateBlock.php b/samples/Sample_23_TemplateBlock.php index 2b7e9f6856..ed986618ba 100644 --- a/samples/Sample_23_TemplateBlock.php +++ b/samples/Sample_23_TemplateBlock.php @@ -14,7 +14,7 @@ echo date('H:i:s'), ' Saving the result document...', EOL; $templateProcessor->saveAs('results/Sample_23_TemplateBlock.docx'); -echo getEndingNotes(array('Word2007' => 'docx')); +echo getEndingNotes(array('Word2007' => 'docx'), 'results/Sample_23_TemplateBlock.docx'); if (!CLI) { include_once 'Sample_Footer.php'; } From 58c6c52ee94b5b1821f9c2fad7ee415fd4fca1c6 Mon Sep 17 00:00:00 2001 From: Javier Garcia Date: Wed, 23 May 2018 18:22:54 +0200 Subject: [PATCH 101/135] merged with local version --- src/PhpWord/Shared/Html.php | 51 +++++++++++++++++++++++++++-- tests/PhpWord/Shared/HtmlTest.php | 54 +++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 2 deletions(-) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index cbdcecd537..b308ec3e4d 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -22,6 +22,7 @@ use PhpOffice\PhpWord\Element\Table; use PhpOffice\PhpWord\SimpleType\Jc; use PhpOffice\PhpWord\SimpleType\NumberFormat; +use PhpOffice\PhpWord\Settings; /** * Common Html functions @@ -32,6 +33,7 @@ class Html { private static $listIndex = 0; private static $xpath; + private static $options; /** * Add HTML parts. @@ -44,13 +46,17 @@ class Html * @param string $html The code to parse * @param bool $fullHTML If it's a full HTML, no need to add 'body' tag * @param bool $preserveWhiteSpace If false, the whitespaces between nodes will be removed + * @param array $options: + * + IMG_SRC_SEARCH: optional to speed up images loading from remote url when files can be found locally + * + IMG_SRC_REPLACE: optional to speed up images loading from remote url when files can be found locally */ - public static function addHtml($element, $html, $fullHTML = false, $preserveWhiteSpace = true) + public static function addHtml($element, $html, $fullHTML = false, $preserveWhiteSpace = true, $options = null ) { /* * @todo parse $stylesheet for default styles. Should result in an array based on id, class and element, * which could be applied when such an element occurs in the parseNode function. */ + self::$options = $options; // Preprocess: remove all line ends, decode HTML entity, // fix ampersand and angle brackets and add body tag for HTML fragments @@ -141,6 +147,7 @@ protected static function parseNode($node, $element, $styles = array(), $data = 'sup' => array('Property', null, null, $styles, null, 'superScript', true), 'sub' => array('Property', null, null, $styles, null, 'subScript', true), 'span' => array('Span', $node, null, $styles, null, null, null), + 'font' => array('Span', $node, null, $styles, null, null, null), 'table' => array('Table', $node, $element, $styles, null, null, null), 'tr' => array('Row', $node, $element, $styles, null, null, null), 'td' => array('Cell', $node, $element, $styles, null, null, null), @@ -296,8 +303,9 @@ private static function parseSpan($node, &$styles) * * @todo As soon as TableItem, RowItem and CellItem support relative width and height */ - private static function parseTable($node, $element, &$styles) + private static function parseTable($node, $element, &$styles ) { + $elementStyles = self::parseInlineStyle($node, $styles['table']); $newElement = $element->addTable($elementStyles); @@ -648,6 +656,45 @@ private static function parseImage($node, $element) break; } } + if( strpos( $src, "data:image" ) !== false ){ + if( ! is_dir( self::$imgdir ) ) + mkdir( self::$imgdir ) ; + + $match = array(); + preg_match( '/data:image\/(\w+);base64,(.+)/', $src, $match ); + + $src = $imgFile = self::$imgdir . uniqid() . "." . $match[1]; + + $ifp = fopen( $imgFile, "wb"); + + fwrite($ifp, base64_decode( $match[2] ) ); + fclose($ifp); + + } + $src= urldecode($src); + + if( ! is_file( $src ) + && !is_null(self::$options) + && isset(self::$options['IMG_SRC_SEARCH']) + && isset(self::$options['IMG_SRC_REPLACE'])){ + $src = str_replace( self::$options['IMG_SRC_SEARCH'], self::$options['IMG_SRC_REPLACE'], $src ); + } + + if(! is_file($src)){ + if($imgBlob=file_get_contents($src)){ + $tmpDir= Settings::getTempDir().'/'; + if( ! is_dir( $tmpDir ) ) + mkdir( $tmpDir ) ; + $match = array(); + preg_match( '/.+\.(\w+)$/', $src, $match ); + $src = $tmpDir . uniqid() . "." . $match[1]; + + $ifp = fopen( $src, "wb"); + + fwrite($ifp, $imgBlob ); + fclose($ifp); + } + } $newElement = $element->addImage($src, $style); return $newElement; diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index b61418e01c..63295d6252 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -115,6 +115,20 @@ public function testParseTextDecoration() $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:rPr/w:u')); $this->assertEquals('single', $doc->getElementAttribute('/w:document/w:body/w:p/w:r/w:rPr/w:u', 'w:val')); } + /** + * Test font + */ + public function testParseFont() + { + $html = 'test'; + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + Html::addHtml($section, $html); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:rPr')); + //TODO check style + } /** * Test line-height style @@ -447,6 +461,46 @@ public function testParseImage() $this->assertStringMatchesFormat('%Smso-position-horizontal:left%S', $doc->getElementAttribute($baseXpath . '[2]/w:pict/v:shape', 'style')); } + /** + * Test parsing of remote img + */ + public function testParseRemoteImage() + { + $src = 'https://phpword.readthedocs.io/en/latest/_images/phpword.png'; + + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + $html = '

        '; + Html::addHtml($section, $html); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $baseXpath = '/w:document/w:body/w:p/w:r'; + $this->assertTrue($doc->elementExists($baseXpath . '/w:pict/v:shape')); + } + /** + * Test parsing of remote img that can be found locally + */ + public function testParseRemoteLocalImage() + { + $src = 'https://fakedomain.io/images/firefox.png'; + $localPath = __DIR__ . '/../_files/images/'; + $options= [ + 'IMG_SRC_SEARCH'=> 'https://fakedomain.io/images/', + 'IMG_SRC_REPLACE'=> $localPath + ]; + + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + $html = '

        '; + Html::addHtml($section, $html, false, true, $options); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $baseXpath = '/w:document/w:body/w:p/w:r'; + $this->assertTrue($doc->elementExists($baseXpath . '/w:pict/v:shape')); + } + public function testParseLink() { $phpWord = new \PhpOffice\PhpWord\PhpWord(); From d54cc6efeea1a43419d9b97a759a796c1124aa6e Mon Sep 17 00:00:00 2001 From: Javier Garcia Date: Wed, 23 May 2018 18:35:12 +0200 Subject: [PATCH 102/135] fix lint --- samples/resources/Sample_30_ReadHTML.html | 6 ++++++ tests/PhpWord/Shared/HtmlTest.php | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/samples/resources/Sample_30_ReadHTML.html b/samples/resources/Sample_30_ReadHTML.html index 5593298bfb..ea98221874 100644 --- a/samples/resources/Sample_30_ReadHTML.html +++ b/samples/resources/Sample_30_ReadHTML.html @@ -11,5 +11,11 @@

        Adding element via HTML

        • Item 1
        • Item 2
          • Item 2.1
          • Item 2.1

        Ordered (numbered) list:

        1. Item 1
        2. Item 2
        + + +

        Double height

        + +

        Includes images

        + diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index 63295d6252..9b5def8525 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -485,10 +485,10 @@ public function testParseRemoteLocalImage() { $src = 'https://fakedomain.io/images/firefox.png'; $localPath = __DIR__ . '/../_files/images/'; - $options= [ + $options= array( 'IMG_SRC_SEARCH'=> 'https://fakedomain.io/images/', 'IMG_SRC_REPLACE'=> $localPath - ]; + ); $phpWord = new \PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); From a228811a611fe015c3bdb916d33ec579aa5697b4 Mon Sep 17 00:00:00 2001 From: Javier Garcia Date: Wed, 23 May 2018 18:48:28 +0200 Subject: [PATCH 103/135] fixes --- src/PhpWord/Shared/Html.php | 72 +++++++++++++++---------------- tests/PhpWord/Shared/HtmlTest.php | 8 ++-- 2 files changed, 41 insertions(+), 39 deletions(-) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index b308ec3e4d..24f695c790 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -20,9 +20,9 @@ use PhpOffice\PhpWord\Element\AbstractContainer; use PhpOffice\PhpWord\Element\Row; use PhpOffice\PhpWord\Element\Table; +use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\SimpleType\Jc; use PhpOffice\PhpWord\SimpleType\NumberFormat; -use PhpOffice\PhpWord\Settings; /** * Common Html functions @@ -50,7 +50,7 @@ class Html * + IMG_SRC_SEARCH: optional to speed up images loading from remote url when files can be found locally * + IMG_SRC_REPLACE: optional to speed up images loading from remote url when files can be found locally */ - public static function addHtml($element, $html, $fullHTML = false, $preserveWhiteSpace = true, $options = null ) + public static function addHtml($element, $html, $fullHTML = false, $preserveWhiteSpace = true, $options = null) { /* * @todo parse $stylesheet for default styles. Should result in an array based on id, class and element, @@ -303,9 +303,8 @@ private static function parseSpan($node, &$styles) * * @todo As soon as TableItem, RowItem and CellItem support relative width and height */ - private static function parseTable($node, $element, &$styles ) + private static function parseTable($node, $element, &$styles) { - $elementStyles = self::parseInlineStyle($node, $styles['table']); $newElement = $element->addTable($elementStyles); @@ -656,45 +655,46 @@ private static function parseImage($node, $element) break; } } - if( strpos( $src, "data:image" ) !== false ){ - if( ! is_dir( self::$imgdir ) ) - mkdir( self::$imgdir ) ; - - $match = array(); - preg_match( '/data:image\/(\w+);base64,(.+)/', $src, $match ); + if (strpos($src, 'data:image') !== false) { + if (!is_dir(self::$imgdir)) { + mkdir(self::$imgdir); + } - $src = $imgFile = self::$imgdir . uniqid() . "." . $match[1]; + $match = array(); + preg_match('/data:image\/(\w+);base64,(.+)/', $src, $match); - $ifp = fopen( $imgFile, "wb"); + $src = $imgFile = self::$imgdir . uniqid() . '.' . $match[1]; - fwrite($ifp, base64_decode( $match[2] ) ); - fclose($ifp); + $ifp = fopen($imgFile, 'wb'); - } - $src= urldecode($src); + fwrite($ifp, base64_decode($match[2])); + fclose($ifp); + } + $src = urldecode($src); - if( ! is_file( $src ) + if (!is_file($src) && !is_null(self::$options) && isset(self::$options['IMG_SRC_SEARCH']) - && isset(self::$options['IMG_SRC_REPLACE'])){ - $src = str_replace( self::$options['IMG_SRC_SEARCH'], self::$options['IMG_SRC_REPLACE'], $src ); - } - - if(! is_file($src)){ - if($imgBlob=file_get_contents($src)){ - $tmpDir= Settings::getTempDir().'/'; - if( ! is_dir( $tmpDir ) ) - mkdir( $tmpDir ) ; - $match = array(); - preg_match( '/.+\.(\w+)$/', $src, $match ); - $src = $tmpDir . uniqid() . "." . $match[1]; - - $ifp = fopen( $src, "wb"); - - fwrite($ifp, $imgBlob ); - fclose($ifp); - } - } + && isset(self::$options['IMG_SRC_REPLACE'])) { + $src = str_replace(self::$options['IMG_SRC_SEARCH'], self::$options['IMG_SRC_REPLACE'], $src); + } + + if (!is_file($src)) { + if ($imgBlob = file_get_contents($src)) { + $tmpDir = Settings::getTempDir() . '/'; + if (!is_dir($tmpDir)) { + mkdir($tmpDir); + } + $match = array(); + preg_match('/.+\.(\w+)$/', $src, $match); + $src = $tmpDir . uniqid() . '.' . $match[1]; + + $ifp = fopen($src, 'wb'); + + fwrite($ifp, $imgBlob); + fclose($ifp); + } + } $newElement = $element->addImage($src, $style); return $newElement; diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index 9b5def8525..8c42544d52 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -115,6 +115,7 @@ public function testParseTextDecoration() $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:rPr/w:u')); $this->assertEquals('single', $doc->getElementAttribute('/w:document/w:body/w:p/w:r/w:rPr/w:u', 'w:val')); } + /** * Test font */ @@ -478,6 +479,7 @@ public function testParseRemoteImage() $baseXpath = '/w:document/w:body/w:p/w:r'; $this->assertTrue($doc->elementExists($baseXpath . '/w:pict/v:shape')); } + /** * Test parsing of remote img that can be found locally */ @@ -485,9 +487,9 @@ public function testParseRemoteLocalImage() { $src = 'https://fakedomain.io/images/firefox.png'; $localPath = __DIR__ . '/../_files/images/'; - $options= array( - 'IMG_SRC_SEARCH'=> 'https://fakedomain.io/images/', - 'IMG_SRC_REPLACE'=> $localPath + $options = array( + 'IMG_SRC_SEARCH' => 'https://fakedomain.io/images/', + 'IMG_SRC_REPLACE' => $localPath, ); $phpWord = new \PhpOffice\PhpWord\PhpWord(); From 46b7bea0975eb70a4cd6d8469d7fa859e277ec6e Mon Sep 17 00:00:00 2001 From: Javier Garcia Date: Thu, 24 May 2018 07:19:45 +0200 Subject: [PATCH 104/135] increased test coverage of new lines --- src/PhpWord/Shared/Html.php | 9 ++------- tests/PhpWord/Shared/HtmlTest.php | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 24f695c790..97b2701875 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -656,14 +656,12 @@ private static function parseImage($node, $element) } } if (strpos($src, 'data:image') !== false) { - if (!is_dir(self::$imgdir)) { - mkdir(self::$imgdir); - } + $tmpDir = Settings::getTempDir() . '/'; $match = array(); preg_match('/data:image\/(\w+);base64,(.+)/', $src, $match); - $src = $imgFile = self::$imgdir . uniqid() . '.' . $match[1]; + $src = $imgFile = $tmpDir . uniqid() . '.' . $match[1]; $ifp = fopen($imgFile, 'wb'); @@ -682,9 +680,6 @@ private static function parseImage($node, $element) if (!is_file($src)) { if ($imgBlob = file_get_contents($src)) { $tmpDir = Settings::getTempDir() . '/'; - if (!is_dir($tmpDir)) { - mkdir($tmpDir); - } $match = array(); preg_match('/.+\.(\w+)$/', $src, $match); $src = $tmpDir . uniqid() . '.' . $match[1]; diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index 8c42544d52..6925e3c20e 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -480,6 +480,22 @@ public function testParseRemoteImage() $this->assertTrue($doc->elementExists($baseXpath . '/w:pict/v:shape')); } + /** + * Test parsing embedded image + */ + public function testParseEmbeddedImage() + { + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + $html = '

        '; + Html::addHtml($section, $html); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $baseXpath = '/w:document/w:body/w:p/w:r'; + $this->assertTrue($doc->elementExists($baseXpath . '/w:pict/v:shape')); + } + /** * Test parsing of remote img that can be found locally */ From a89e4c93a78c964bd3b7e6dc5f1ab38bb0d18525 Mon Sep 17 00:00:00 2001 From: Javier Garcia Date: Fri, 25 May 2018 08:01:17 +0200 Subject: [PATCH 105/135] added exception control to file_get_contents error --- samples/resources/Sample_30_ReadHTML.html | 6 +++++- samples/results/.gitignore | 0 src/PhpWord/Shared/Html.php | 10 ++++++++-- tests/PhpWord/Shared/HtmlTest.php | 14 ++++++++++++++ 4 files changed, 27 insertions(+), 3 deletions(-) mode change 100644 => 100755 samples/results/.gitignore diff --git a/samples/resources/Sample_30_ReadHTML.html b/samples/resources/Sample_30_ReadHTML.html index ea98221874..b3d2fad222 100644 --- a/samples/resources/Sample_30_ReadHTML.html +++ b/samples/resources/Sample_30_ReadHTML.html @@ -12,10 +12,14 @@

        Adding element via HTML

        Ordered (numbered) list:

        1. Item 1
        2. Item 2
        -

        Double height

        Includes images

        + + + + + diff --git a/samples/results/.gitignore b/samples/results/.gitignore old mode 100644 new mode 100755 diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 97b2701875..231727693c 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -655,6 +655,7 @@ private static function parseImage($node, $element) break; } } + $origin_src= $src; if (strpos($src, 'data:image') !== false) { $tmpDir = Settings::getTempDir() . '/'; @@ -678,7 +679,7 @@ private static function parseImage($node, $element) } if (!is_file($src)) { - if ($imgBlob = file_get_contents($src)) { + if ($imgBlob = @file_get_contents($src)) { $tmpDir = Settings::getTempDir() . '/'; $match = array(); preg_match('/.+\.(\w+)$/', $src, $match); @@ -690,7 +691,12 @@ private static function parseImage($node, $element) fclose($ifp); } } - $newElement = $element->addImage($src, $style); + + if (is_file($src)){ + $newElement = $element->addImage($src, $style); + }else{ + throw new \Exception("Could not load image $origin_src"); + } return $newElement; } diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index 6925e3c20e..481b5d75bc 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -519,6 +519,20 @@ public function testParseRemoteLocalImage() $this->assertTrue($doc->elementExists($baseXpath . '/w:pict/v:shape')); } + /** + * Test parsing of remote img that can be found locally + */ + public function testCouldNotLoadImage() + { + $src = 'https://fakedomain.io/images/firefox.png'; + $this->expectException(\Exception::class); + + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + $html = '

        '; + Html::addHtml($section, $html, false, true); + } + public function testParseLink() { $phpWord = new \PhpOffice\PhpWord\PhpWord(); From 65a594d2713b6ff876ca0a1d230404a0d160b6c9 Mon Sep 17 00:00:00 2001 From: Javier Garcia Date: Fri, 25 May 2018 09:29:58 +0200 Subject: [PATCH 106/135] cs-fixer fixes --- src/PhpWord/Shared/Html.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 231727693c..58ce241288 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -655,7 +655,7 @@ private static function parseImage($node, $element) break; } } - $origin_src= $src; + $originSrc = $src; if (strpos($src, 'data:image') !== false) { $tmpDir = Settings::getTempDir() . '/'; @@ -692,10 +692,10 @@ private static function parseImage($node, $element) } } - if (is_file($src)){ - $newElement = $element->addImage($src, $style); - }else{ - throw new \Exception("Could not load image $origin_src"); + if (is_file($src)) { + $newElement = $element->addImage($src, $style); + } else { + throw new \Exception("Could not load image $originSrc"); } return $newElement; From 0c9626cedd0efe20de858c96cc9ba3fb2e2d78f1 Mon Sep 17 00:00:00 2001 From: troosan Date: Sun, 27 May 2018 20:38:25 +0200 Subject: [PATCH 107/135] add .gitattributes --- .gitattributes | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..f3d033a781 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,21 @@ +# build config +/.scrutinizer.yml export-ignore +/.travis.yml export-ignore +/php_cs.dist export-ignore +/phpmd.xml.dist export-ignore +/phpstan.neon export-ignore + +/composer.lock export-ignore + +# git files +/.gitignore export-ignore +/.gitattributes export-ignore + +# project directories +/build export-ignore +/docs export-ignore +/samples export-ignore + +# tests +/phpunit.xml.dist export-ignore +/tests export-ignore \ No newline at end of file From da604a80c43241b28c7cf6d07977f1533a70d39c Mon Sep 17 00:00:00 2001 From: troosan Date: Sun, 27 May 2018 20:53:42 +0200 Subject: [PATCH 108/135] use annotation instead --- tests/PhpWord/Shared/HtmlTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index 481b5d75bc..32f4bf460c 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -521,11 +521,12 @@ public function testParseRemoteLocalImage() /** * Test parsing of remote img that can be found locally + * + * @expectedException \Exception */ public function testCouldNotLoadImage() { $src = 'https://fakedomain.io/images/firefox.png'; - $this->expectException(\Exception::class); $phpWord = new \PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); From c22f7eab5e2a9e764946ddf77c8f82d21811871a Mon Sep 17 00:00:00 2001 From: troosan Date: Sun, 27 May 2018 21:27:45 +0200 Subject: [PATCH 109/135] add check on opened file --- src/PhpWord/Shared/Html.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 58ce241288..239cfd1dbb 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -666,8 +666,10 @@ private static function parseImage($node, $element) $ifp = fopen($imgFile, 'wb'); - fwrite($ifp, base64_decode($match[2])); - fclose($ifp); + if ($ifp !== false) { + fwrite($ifp, base64_decode($match[2])); + fclose($ifp); + } } $src = urldecode($src); @@ -687,8 +689,10 @@ private static function parseImage($node, $element) $ifp = fopen($src, 'wb'); - fwrite($ifp, $imgBlob); - fclose($ifp); + if ($ifp !== false) { + fwrite($ifp, $imgBlob); + fclose($ifp); + } } } From 82f3a2ab44f9de047087e5307fdb9269fb346e0c Mon Sep 17 00:00:00 2001 From: Edvin Hultberg Date: Thu, 31 May 2018 00:21:08 +0200 Subject: [PATCH 110/135] Update documentation for Style::add*Style methods (#1383) * Update documentation for Style::add*Style methods * remove phpDocumentor, simplify dependencies --- .travis.yml | 4 ++-- composer.json | 7 +++---- src/PhpWord/Element/AbstractElement.php | 2 +- src/PhpWord/PhpWord.php | 4 ++-- src/PhpWord/Style.php | 20 ++++++++++---------- src/PhpWord/Style/Font.php | 2 +- 6 files changed, 19 insertions(+), 20 deletions(-) diff --git a/.travis.yml b/.travis.yml index bd85b2d77e..c72dd8c298 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,7 +37,7 @@ before_script: - composer self-update - travis_wait composer install --prefer-source ## PHPDocumentor - - mkdir -p build/docs + ##- mkdir -p build/docs - mkdir -p build/coverage script: @@ -52,7 +52,7 @@ script: ## PHPLOC - if [ -z "$COVERAGE" ]; then ./vendor/bin/phploc src/ ; fi ## PHPDocumentor - - if [ -z "$COVERAGE" ]; then ./vendor/bin/phpdoc -q -d ./src -t ./build/docs --ignore "*/src/PhpWord/Shared/*/*" --template="responsive-twig" ; fi + ##- if [ -z "$COVERAGE" ]; then ./vendor/bin/phpdoc -q -d ./src -t ./build/docs --ignore "*/src/PhpWord/Shared/*/*" --template="responsive-twig" ; fi after_success: ## Coveralls diff --git a/composer.json b/composer.json index c29e901a38..dd3a2de857 100644 --- a/composer.json +++ b/composer.json @@ -65,14 +65,13 @@ }, "require-dev": { "phpunit/phpunit": "^4.8.36 || ^5.0", - "phpdocumentor/phpdocumentor":"2.*", - "squizlabs/php_codesniffer": "^2.7", - "friendsofphp/php-cs-fixer": "^2.0", + "squizlabs/php_codesniffer": "^2.9", + "friendsofphp/php-cs-fixer": "^2.2", "phpmd/phpmd": "2.*", "phploc/phploc": "2.* || 3.* || 4.*", "dompdf/dompdf":"0.8.*", "tecnickcom/tcpdf": "6.*", - "mpdf/mpdf": "5.* || 6.* || 7.*", + "mpdf/mpdf": "5.7.4 || 6.* || 7.*", "php-coveralls/php-coveralls": "1.1.0 || ^2.0" }, "suggest": { diff --git a/src/PhpWord/Element/AbstractElement.php b/src/PhpWord/Element/AbstractElement.php index 5ff85b8fb1..e3e54ed426 100644 --- a/src/PhpWord/Element/AbstractElement.php +++ b/src/PhpWord/Element/AbstractElement.php @@ -347,7 +347,7 @@ public function getParent() * * @param \PhpOffice\PhpWord\Element\AbstractElement $container */ - public function setParentContainer(AbstractElement $container) + public function setParentContainer(self $container) { $this->parentContainer = substr(get_class($container), strrpos(get_class($container), '\\') + 1); $this->parent = $container; diff --git a/src/PhpWord/PhpWord.php b/src/PhpWord/PhpWord.php index b5cc0c5151..a78df2c4e5 100644 --- a/src/PhpWord/PhpWord.php +++ b/src/PhpWord/PhpWord.php @@ -35,10 +35,10 @@ * @method int addChart(Element\Chart $chart) * @method int addComment(Element\Comment $comment) * - * @method Style\Paragraph addParagraphStyle(string $styleName, array $styles) + * @method Style\Paragraph addParagraphStyle(string $styleName, mixed $styles) * @method Style\Font addFontStyle(string $styleName, mixed $fontStyle, mixed $paragraphStyle = null) * @method Style\Font addLinkStyle(string $styleName, mixed $styles) - * @method Style\Font addTitleStyle(int $depth, mixed $fontStyle, mixed $paragraphStyle = null) + * @method Style\Font addTitleStyle(mixed $depth, mixed $fontStyle, mixed $paragraphStyle = null) * @method Style\Table addTableStyle(string $styleName, mixed $styleTable, mixed $styleFirstRow = null) * @method Style\Numbering addNumberingStyle(string $styleName, mixed $styles) */ diff --git a/src/PhpWord/Style.php b/src/PhpWord/Style.php index 47242621df..62783b6301 100644 --- a/src/PhpWord/Style.php +++ b/src/PhpWord/Style.php @@ -39,7 +39,7 @@ class Style * Add paragraph style * * @param string $styleName - * @param array $styles + * @param array|\PhpOffice\PhpWord\Style\AbstractStyle $styles * @return \PhpOffice\PhpWord\Style\Paragraph */ public static function addParagraphStyle($styleName, $styles) @@ -51,8 +51,8 @@ public static function addParagraphStyle($styleName, $styles) * Add font style * * @param string $styleName - * @param array $fontStyle - * @param array $paragraphStyle + * @param array|\PhpOffice\PhpWord\Style\AbstractStyle $fontStyle + * @param array|\PhpOffice\PhpWord\Style\AbstractStyle $paragraphStyle * @return \PhpOffice\PhpWord\Style\Font */ public static function addFontStyle($styleName, $fontStyle, $paragraphStyle = null) @@ -64,7 +64,7 @@ public static function addFontStyle($styleName, $fontStyle, $paragraphStyle = nu * Add link style * * @param string $styleName - * @param array $styles + * @param array|\PhpOffice\PhpWord\Style\AbstractStyle $styles * @return \PhpOffice\PhpWord\Style\Font */ public static function addLinkStyle($styleName, $styles) @@ -76,7 +76,7 @@ public static function addLinkStyle($styleName, $styles) * Add numbering style * * @param string $styleName - * @param array $styleValues + * @param array|\PhpOffice\PhpWord\Style\AbstractStyle $styleValues * @return \PhpOffice\PhpWord\Style\Numbering * @since 0.10.0 */ @@ -88,14 +88,14 @@ public static function addNumberingStyle($styleName, $styleValues) /** * Add title style * - * @param int $depth - * @param array $fontStyle - * @param array $paragraphStyle + * @param int|null $depth Provide null to set title font + * @param array|\PhpOffice\PhpWord\Style\AbstractStyle $fontStyle + * @param array|\PhpOffice\PhpWord\Style\AbstractStyle $paragraphStyle * @return \PhpOffice\PhpWord\Style\Font */ public static function addTitleStyle($depth, $fontStyle, $paragraphStyle = null) { - if ($depth == null) { + if (empty($depth)) { $styleName = 'Title'; } else { $styleName = "Heading_{$depth}"; @@ -141,7 +141,7 @@ public static function resetStyles() /** * Set default paragraph style * - * @param array $styles Paragraph style definition + * @param array|\PhpOffice\PhpWord\Style\AbstractStyle $styles Paragraph style definition * @return \PhpOffice\PhpWord\Style\Paragraph */ public static function setDefaultParagraphStyle($styles) diff --git a/src/PhpWord/Style/Font.php b/src/PhpWord/Style/Font.php index c58cee49ed..e9f3c9d672 100644 --- a/src/PhpWord/Style/Font.php +++ b/src/PhpWord/Style/Font.php @@ -264,7 +264,7 @@ class Font extends AbstractStyle * Create new font style * * @param string $type Type of font - * @param array $paragraph Paragraph styles definition + * @param array|string|\PhpOffice\PhpWord\Style\AbstractStyle $paragraph Paragraph styles definition */ public function __construct($type = 'text', $paragraph = null) { From e76487172b78af26e44b250f85d41fce541f5084 Mon Sep 17 00:00:00 2001 From: troosan Date: Thu, 31 May 2018 00:31:41 +0200 Subject: [PATCH 111/135] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dfcce5a4d2..e7b7ed6869 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ v0.15.0 (?? ??? 2018) - Add support for table indent (tblInd) @Trainmaster #1343 - Added parsing of internal links in HTML reader @lalop #1336 - Several improvements to charts @JAEK-S #1332 +- Add parsing of html image in base64 format @jgpATs2w #1382 ### Fixed - Fix reading of docx default style - @troosan #1238 From 1a06173e1b933cbb8945949aca3d6a90179b496e Mon Sep 17 00:00:00 2001 From: javier Date: Thu, 31 May 2018 01:28:14 +0200 Subject: [PATCH 112/135] Add parsing of html image in base64 format (#1382) * increased test coverage of new lines * added exception control to file_get_contents error * update changelog --- CHANGELOG.md | 1 + samples/resources/Sample_30_ReadHTML.html | 10 +++ samples/results/.gitignore | 0 src/PhpWord/Shared/Html.php | 56 ++++++++++++++- tests/PhpWord/Shared/HtmlTest.php | 87 +++++++++++++++++++++++ 5 files changed, 152 insertions(+), 2 deletions(-) mode change 100644 => 100755 samples/results/.gitignore diff --git a/CHANGELOG.md b/CHANGELOG.md index dfcce5a4d2..e7b7ed6869 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ v0.15.0 (?? ??? 2018) - Add support for table indent (tblInd) @Trainmaster #1343 - Added parsing of internal links in HTML reader @lalop #1336 - Several improvements to charts @JAEK-S #1332 +- Add parsing of html image in base64 format @jgpATs2w #1382 ### Fixed - Fix reading of docx default style - @troosan #1238 diff --git a/samples/resources/Sample_30_ReadHTML.html b/samples/resources/Sample_30_ReadHTML.html index 5593298bfb..b3d2fad222 100644 --- a/samples/resources/Sample_30_ReadHTML.html +++ b/samples/resources/Sample_30_ReadHTML.html @@ -11,5 +11,15 @@

        Adding element via HTML

        • Item 1
        • Item 2
          • Item 2.1
          • Item 2.1

        Ordered (numbered) list:

        1. Item 1
        2. Item 2
        + +

        Double height

        + +

        Includes images

        + + + + + + diff --git a/samples/results/.gitignore b/samples/results/.gitignore old mode 100644 new mode 100755 diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index cbdcecd537..239cfd1dbb 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -20,6 +20,7 @@ use PhpOffice\PhpWord\Element\AbstractContainer; use PhpOffice\PhpWord\Element\Row; use PhpOffice\PhpWord\Element\Table; +use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\SimpleType\Jc; use PhpOffice\PhpWord\SimpleType\NumberFormat; @@ -32,6 +33,7 @@ class Html { private static $listIndex = 0; private static $xpath; + private static $options; /** * Add HTML parts. @@ -44,13 +46,17 @@ class Html * @param string $html The code to parse * @param bool $fullHTML If it's a full HTML, no need to add 'body' tag * @param bool $preserveWhiteSpace If false, the whitespaces between nodes will be removed + * @param array $options: + * + IMG_SRC_SEARCH: optional to speed up images loading from remote url when files can be found locally + * + IMG_SRC_REPLACE: optional to speed up images loading from remote url when files can be found locally */ - public static function addHtml($element, $html, $fullHTML = false, $preserveWhiteSpace = true) + public static function addHtml($element, $html, $fullHTML = false, $preserveWhiteSpace = true, $options = null) { /* * @todo parse $stylesheet for default styles. Should result in an array based on id, class and element, * which could be applied when such an element occurs in the parseNode function. */ + self::$options = $options; // Preprocess: remove all line ends, decode HTML entity, // fix ampersand and angle brackets and add body tag for HTML fragments @@ -141,6 +147,7 @@ protected static function parseNode($node, $element, $styles = array(), $data = 'sup' => array('Property', null, null, $styles, null, 'superScript', true), 'sub' => array('Property', null, null, $styles, null, 'subScript', true), 'span' => array('Span', $node, null, $styles, null, null, null), + 'font' => array('Span', $node, null, $styles, null, null, null), 'table' => array('Table', $node, $element, $styles, null, null, null), 'tr' => array('Row', $node, $element, $styles, null, null, null), 'td' => array('Cell', $node, $element, $styles, null, null, null), @@ -648,7 +655,52 @@ private static function parseImage($node, $element) break; } } - $newElement = $element->addImage($src, $style); + $originSrc = $src; + if (strpos($src, 'data:image') !== false) { + $tmpDir = Settings::getTempDir() . '/'; + + $match = array(); + preg_match('/data:image\/(\w+);base64,(.+)/', $src, $match); + + $src = $imgFile = $tmpDir . uniqid() . '.' . $match[1]; + + $ifp = fopen($imgFile, 'wb'); + + if ($ifp !== false) { + fwrite($ifp, base64_decode($match[2])); + fclose($ifp); + } + } + $src = urldecode($src); + + if (!is_file($src) + && !is_null(self::$options) + && isset(self::$options['IMG_SRC_SEARCH']) + && isset(self::$options['IMG_SRC_REPLACE'])) { + $src = str_replace(self::$options['IMG_SRC_SEARCH'], self::$options['IMG_SRC_REPLACE'], $src); + } + + if (!is_file($src)) { + if ($imgBlob = @file_get_contents($src)) { + $tmpDir = Settings::getTempDir() . '/'; + $match = array(); + preg_match('/.+\.(\w+)$/', $src, $match); + $src = $tmpDir . uniqid() . '.' . $match[1]; + + $ifp = fopen($src, 'wb'); + + if ($ifp !== false) { + fwrite($ifp, $imgBlob); + fclose($ifp); + } + } + } + + if (is_file($src)) { + $newElement = $element->addImage($src, $style); + } else { + throw new \Exception("Could not load image $originSrc"); + } return $newElement; } diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index b61418e01c..32f4bf460c 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -116,6 +116,21 @@ public function testParseTextDecoration() $this->assertEquals('single', $doc->getElementAttribute('/w:document/w:body/w:p/w:r/w:rPr/w:u', 'w:val')); } + /** + * Test font + */ + public function testParseFont() + { + $html = 'test'; + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + Html::addHtml($section, $html); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:rPr')); + //TODO check style + } + /** * Test line-height style */ @@ -447,6 +462,78 @@ public function testParseImage() $this->assertStringMatchesFormat('%Smso-position-horizontal:left%S', $doc->getElementAttribute($baseXpath . '[2]/w:pict/v:shape', 'style')); } + /** + * Test parsing of remote img + */ + public function testParseRemoteImage() + { + $src = 'https://phpword.readthedocs.io/en/latest/_images/phpword.png'; + + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + $html = '

        '; + Html::addHtml($section, $html); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $baseXpath = '/w:document/w:body/w:p/w:r'; + $this->assertTrue($doc->elementExists($baseXpath . '/w:pict/v:shape')); + } + + /** + * Test parsing embedded image + */ + public function testParseEmbeddedImage() + { + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + $html = '

        '; + Html::addHtml($section, $html); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $baseXpath = '/w:document/w:body/w:p/w:r'; + $this->assertTrue($doc->elementExists($baseXpath . '/w:pict/v:shape')); + } + + /** + * Test parsing of remote img that can be found locally + */ + public function testParseRemoteLocalImage() + { + $src = 'https://fakedomain.io/images/firefox.png'; + $localPath = __DIR__ . '/../_files/images/'; + $options = array( + 'IMG_SRC_SEARCH' => 'https://fakedomain.io/images/', + 'IMG_SRC_REPLACE' => $localPath, + ); + + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + $html = '

        '; + Html::addHtml($section, $html, false, true, $options); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $baseXpath = '/w:document/w:body/w:p/w:r'; + $this->assertTrue($doc->elementExists($baseXpath . '/w:pict/v:shape')); + } + + /** + * Test parsing of remote img that can be found locally + * + * @expectedException \Exception + */ + public function testCouldNotLoadImage() + { + $src = 'https://fakedomain.io/images/firefox.png'; + + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + $html = '

        '; + Html::addHtml($section, $html, false, true); + } + public function testParseLink() { $phpWord = new \PhpOffice\PhpWord\PhpWord(); From aa271091016a2ae8a793b404fcb170d37b87bbd3 Mon Sep 17 00:00:00 2001 From: Omar Piani Date: Thu, 31 May 2018 11:43:20 +0200 Subject: [PATCH 113/135] Update Language.php --- src/PhpWord/Style/Language.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/PhpWord/Style/Language.php b/src/PhpWord/Style/Language.php index 4e9220fd44..21c416af75 100644 --- a/src/PhpWord/Style/Language.php +++ b/src/PhpWord/Style/Language.php @@ -46,6 +46,9 @@ final class Language extends AbstractStyle const HE_IL = 'he-IL'; const HE_IL_ID = 1037; + + const IT_IT = 'it-IT'; + const IT_IT_ID = 1040; const JA_JP = 'ja-JP'; const JA_JP_ID = 1041; From 0bd7c0b301494f27e07b5984a5c24ac2d3f934b0 Mon Sep 17 00:00:00 2001 From: troosan Date: Thu, 31 May 2018 19:50:43 +0200 Subject: [PATCH 114/135] Add constants for Italian --- src/PhpWord/Style/Language.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/Style/Language.php b/src/PhpWord/Style/Language.php index 21c416af75..5284bbf321 100644 --- a/src/PhpWord/Style/Language.php +++ b/src/PhpWord/Style/Language.php @@ -46,7 +46,7 @@ final class Language extends AbstractStyle const HE_IL = 'he-IL'; const HE_IL_ID = 1037; - + const IT_IT = 'it-IT'; const IT_IT_ID = 1040; From 4e37afa15da62cdd695a18db2a40d86615086e9d Mon Sep 17 00:00:00 2001 From: troosan Date: Thu, 31 May 2018 20:10:49 +0200 Subject: [PATCH 115/135] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bfb1cb5c27..221377dfba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,7 +34,7 @@ v0.15.0 (?? ??? 2018) - Fix colspan and rowspan for tables in HTML Writer @mattbolt #1292 - Fix parsing of Heading and Title formating @troosan @gthomas2 #465 - Fix Dateformat typo, fix hours casing, add Month-Day-Year formats @ComputerTinker #591 -- Fix missing column with in ODText writer @potofcoffee #413 +- Fix missing column width in ODText writer @potofcoffee #413 ### Changed - Remove zend-stdlib dependency @Trainmaster #1284 From d9ddc162a362cae5ef3842e5d44e052aa946a1e9 Mon Sep 17 00:00:00 2001 From: troosan Date: Wed, 18 Apr 2018 22:34:53 +0200 Subject: [PATCH 116/135] write column width in ODT writer --- CHANGELOG.md | 1 + src/PhpWord/Element/Table.php | 24 +++++++ src/PhpWord/Style/Table.php | 27 ++++++++ src/PhpWord/Writer/ODText/Element/Table.php | 63 ++++++++++++++----- src/PhpWord/Writer/ODText/Part/Content.php | 1 + src/PhpWord/Writer/ODText/Style/Table.php | 13 ++++ src/PhpWord/Writer/Word2007/Element/Table.php | 16 +---- 7 files changed, 114 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7b7ed6869..868a4eba68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ v0.15.0 (?? ??? 2018) - Fix colspan and rowspan for tables in HTML Writer @mattbolt #1292 - Fix parsing of Heading and Title formating @troosan @gthomas2 #465 - Fix Dateformat typo, fix hours casing, add Month-Day-Year formats @ComputerTinker #591 +- Fix missing column with in ODText writer @potofcoffee #413 ### Changed - Remove zend-stdlib dependency @Trainmaster #1284 diff --git a/src/PhpWord/Element/Table.php b/src/PhpWord/Element/Table.php index 10c4db69ab..1610211961 100644 --- a/src/PhpWord/Element/Table.php +++ b/src/PhpWord/Element/Table.php @@ -149,4 +149,28 @@ public function countColumns() return $columnCount; } + + /** + * The first declared cell width for each column + * + * @return int[] + */ + public function findFirstDefinedCellWidths() + { + $cellWidths = array(); + if (is_array($this->rows)) { + foreach ($this->rows as $row) { + $cells = $row->getCells(); + if (count($cells) <= count($cellWidths)) { + continue; + } + $cellWidths = array(); + foreach ($cells as $cell) { + $cellWidths[] = $cell->getWidth(); + } + } + } + + return $cellWidths; + } } diff --git a/src/PhpWord/Style/Table.php b/src/PhpWord/Style/Table.php index b622c78b4a..0f7bf7dc3b 100644 --- a/src/PhpWord/Style/Table.php +++ b/src/PhpWord/Style/Table.php @@ -163,6 +163,13 @@ class Table extends Border /** @var TblWidthComplexType|null */ private $indent; + /** + * The width of each column, computed based on the max cell width of each column + * + * @var int[] + */ + private $columnWidths; + /** * Create new table style * @@ -748,4 +755,24 @@ public function setIndent(TblWidthComplexType $indent) return $this; } + + /** + * Get the columnWidths + * + * @return number[] + */ + public function getColumnWidths() + { + return $this->columnWidths; + } + + /** + * The column widths + * + * @param int[] $value + */ + public function setColumnWidths(array $value = null) + { + $this->columnWidths = $value; + } } diff --git a/src/PhpWord/Writer/ODText/Element/Table.php b/src/PhpWord/Writer/ODText/Element/Table.php index 8a21ee1b47..088330ae5f 100644 --- a/src/PhpWord/Writer/ODText/Element/Table.php +++ b/src/PhpWord/Writer/ODText/Element/Table.php @@ -17,6 +17,10 @@ namespace PhpOffice\PhpWord\Writer\ODText\Element; +use PhpOffice\Common\XMLWriter; +use PhpOffice\PhpWord\Element\Row as RowElement; +use PhpOffice\PhpWord\Element\Table as TableElement; + /** * Table element writer * @@ -36,32 +40,59 @@ public function write() } $rows = $element->getRows(); $rowCount = count($rows); - $colCount = $element->countColumns(); if ($rowCount > 0) { $xmlWriter->startElement('table:table'); $xmlWriter->writeAttribute('table:name', $element->getElementId()); $xmlWriter->writeAttribute('table:style', $element->getElementId()); - $xmlWriter->startElement('table:table-column'); - $xmlWriter->writeAttribute('table:number-columns-repeated', $colCount); - $xmlWriter->endElement(); // table:table-column + // Write columns + $this->writeColumns($xmlWriter, $element); + // Write rows foreach ($rows as $row) { - $xmlWriter->startElement('table:table-row'); - /** @var $row \PhpOffice\PhpWord\Element\Row Type hint */ - foreach ($row->getCells() as $cell) { - $xmlWriter->startElement('table:table-cell'); - $xmlWriter->writeAttribute('office:value-type', 'string'); - - $containerWriter = new Container($xmlWriter, $cell); - $containerWriter->write(); - - $xmlWriter->endElement(); // table:table-cell - } - $xmlWriter->endElement(); // table:table-row + $this->writeRow($xmlWriter, $row); } $xmlWriter->endElement(); // table:table } } + + /** + * Write column. + * + * @param \PhpOffice\Common\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Element\Table $element + */ + private function writeColumns(XMLWriter $xmlWriter, TableElement $element) + { + $colCount = $element->countColumns(); + + for ($i = 0; $i < $colCount; $i++) { + $xmlWriter->startElement('table:table-column'); + $xmlWriter->writeAttribute('table:style-name', $element->getElementId() . '.' . $i); + $xmlWriter->endElement(); + } + } + + /** + * Write row. + * + * @param \PhpOffice\Common\XMLWriter $xmlWriter + * @param \PhpOffice\PhpWord\Element\Row $row + */ + private function writeRow(XMLWriter $xmlWriter, RowElement $row) + { + $xmlWriter->startElement('table:table-row'); + /** @var $row \PhpOffice\PhpWord\Element\Row Type hint */ + foreach ($row->getCells() as $cell) { + $xmlWriter->startElement('table:table-cell'); + $xmlWriter->writeAttribute('office:value-type', 'string'); + + $containerWriter = new Container($xmlWriter, $cell); + $containerWriter->write(); + + $xmlWriter->endElement(); // table:table-cell + } + $xmlWriter->endElement(); // table:table-row + } } diff --git a/src/PhpWord/Writer/ODText/Part/Content.php b/src/PhpWord/Writer/ODText/Part/Content.php index a50eea7ba0..b705bb5e81 100644 --- a/src/PhpWord/Writer/ODText/Part/Content.php +++ b/src/PhpWord/Writer/ODText/Part/Content.php @@ -246,6 +246,7 @@ private function getContainerStyle($container, &$paragraphStyleCount, &$fontStyl $style = Style::getStyle($style); } $style->setStyleName($element->getElementId()); + $style->setColumnWidths($element->findFirstDefinedCellWidths()); $this->autoStyles['Table'][] = $style; } } diff --git a/src/PhpWord/Writer/ODText/Style/Table.php b/src/PhpWord/Writer/ODText/Style/Table.php index 249321cff8..f5a3c431d0 100644 --- a/src/PhpWord/Writer/ODText/Style/Table.php +++ b/src/PhpWord/Writer/ODText/Style/Table.php @@ -45,5 +45,18 @@ public function write() $xmlWriter->writeAttribute('table:align', 'center'); $xmlWriter->endElement(); // style:table-properties $xmlWriter->endElement(); // style:style + + $cellWidths = $style->getColumnWidths(); + + for ($i = 0; $i < count($cellWidths); $i++) { + $width = $cellWidths[$i]; + $xmlWriter->startElement('style:style'); + $xmlWriter->writeAttribute('style:name', $style->getStyleName() . '.' . $i); + $xmlWriter->writeAttribute('style:family', 'table-column'); + $xmlWriter->startElement('style:table-column-properties'); + $xmlWriter->writeAttribute('style:column-width', number_format($width * 0.0017638889, 2, '.', '') . 'cm'); + $xmlWriter->endElement(); // style:table-column-properties + $xmlWriter->endElement(); // style:style + } } } diff --git a/src/PhpWord/Writer/Word2007/Element/Table.php b/src/PhpWord/Writer/Word2007/Element/Table.php index 25a48ab2cc..c365b028ab 100644 --- a/src/PhpWord/Writer/Word2007/Element/Table.php +++ b/src/PhpWord/Writer/Word2007/Element/Table.php @@ -76,21 +76,7 @@ public function write() */ private function writeColumns(XMLWriter $xmlWriter, TableElement $element) { - $rows = $element->getRows(); - $rowCount = count($rows); - - $cellWidths = array(); - for ($i = 0; $i < $rowCount; $i++) { - $row = $rows[$i]; - $cells = $row->getCells(); - if (count($cells) <= count($cellWidths)) { - continue; - } - $cellWidths = array(); - foreach ($cells as $cell) { - $cellWidths[] = $cell->getWidth(); - } - } + $cellWidths = $element->findFirstDefinedCellWidths(); $xmlWriter->startElement('w:tblGrid'); foreach ($cellWidths as $width) { From da43a880e36fc43c6d715cfbb5adb89eee02350f Mon Sep 17 00:00:00 2001 From: troosan Date: Sun, 3 Jun 2018 00:22:08 +0200 Subject: [PATCH 117/135] Address scrutinizer issues --- src/PhpWord/Element/Table.php | 36 ++++++++++------------ src/PhpWord/Writer/ODText/Part/Content.php | 1 + src/PhpWord/Writer/ODText/Style/Table.php | 3 +- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/PhpWord/Element/Table.php b/src/PhpWord/Element/Table.php index 1610211961..44fe3744bd 100644 --- a/src/PhpWord/Element/Table.php +++ b/src/PhpWord/Element/Table.php @@ -135,15 +135,14 @@ public function setWidth($width) public function countColumns() { $columnCount = 0; - if (is_array($this->rows)) { - $rowCount = count($this->rows); - for ($i = 0; $i < $rowCount; $i++) { - /** @var \PhpOffice\PhpWord\Element\Row $row Type hint */ - $row = $this->rows[$i]; - $cellCount = count($row->getCells()); - if ($columnCount < $cellCount) { - $columnCount = $cellCount; - } + + $rowCount = count($this->rows); + for ($i = 0; $i < $rowCount; $i++) { + /** @var \PhpOffice\PhpWord\Element\Row $row Type hint */ + $row = $this->rows[$i]; + $cellCount = count($row->getCells()); + if ($columnCount < $cellCount) { + $columnCount = $cellCount; } } @@ -158,16 +157,15 @@ public function countColumns() public function findFirstDefinedCellWidths() { $cellWidths = array(); - if (is_array($this->rows)) { - foreach ($this->rows as $row) { - $cells = $row->getCells(); - if (count($cells) <= count($cellWidths)) { - continue; - } - $cellWidths = array(); - foreach ($cells as $cell) { - $cellWidths[] = $cell->getWidth(); - } + + foreach ($this->rows as $row) { + $cells = $row->getCells(); + if (count($cells) <= count($cellWidths)) { + continue; + } + $cellWidths = array(); + foreach ($cells as $cell) { + $cellWidths[] = $cell->getWidth(); } } diff --git a/src/PhpWord/Writer/ODText/Part/Content.php b/src/PhpWord/Writer/ODText/Part/Content.php index b705bb5e81..99ee93536e 100644 --- a/src/PhpWord/Writer/ODText/Part/Content.php +++ b/src/PhpWord/Writer/ODText/Part/Content.php @@ -239,6 +239,7 @@ private function getContainerStyle($container, &$paragraphStyleCount, &$fontStyl $style->setStyleName('fr' . $element->getMediaIndex()); $this->autoStyles['Image'][] = $style; } elseif ($element instanceof Table) { + /** @var \PhpOffice\PhpWord\Style\Table $style */ $style = $element->getStyle(); if ($style === null) { $style = new TableStyle(); diff --git a/src/PhpWord/Writer/ODText/Style/Table.php b/src/PhpWord/Writer/ODText/Style/Table.php index f5a3c431d0..5ddee25a3c 100644 --- a/src/PhpWord/Writer/ODText/Style/Table.php +++ b/src/PhpWord/Writer/ODText/Style/Table.php @@ -47,8 +47,9 @@ public function write() $xmlWriter->endElement(); // style:style $cellWidths = $style->getColumnWidths(); + $countCellWidths = count($cellWidths); - for ($i = 0; $i < count($cellWidths); $i++) { + for ($i = 0; $i < $countCellWidths; $i++) { $width = $cellWidths[$i]; $xmlWriter->startElement('style:style'); $xmlWriter->writeAttribute('style:name', $style->getStyleName() . '.' . $i); From 5b9719071e1454bdbd4faa5940ba81636334ca73 Mon Sep 17 00:00:00 2001 From: troosan Date: Sun, 3 Jun 2018 22:36:30 +0200 Subject: [PATCH 118/135] remove unused imports --- samples/Sample_01_SimpleText.php | 1 - tests/PhpWord/Style/PaperTest.php | 1 - tests/PhpWord/Writer/Word2007/Part/SettingsTest.php | 1 - 3 files changed, 3 deletions(-) diff --git a/samples/Sample_01_SimpleText.php b/samples/Sample_01_SimpleText.php index 5a3393b361..8af44d20aa 100644 --- a/samples/Sample_01_SimpleText.php +++ b/samples/Sample_01_SimpleText.php @@ -1,6 +1,5 @@ Date: Wed, 13 Jun 2018 17:41:17 +0200 Subject: [PATCH 119/135] fix when style line-height size comes in decimal number --- samples/resources/Sample_30_ReadHTML.html | 9 ++++++--- src/PhpWord/Shared/Html.php | 2 +- tests/PhpWord/Shared/ConverterTest.php | 1 + tests/PhpWord/Shared/HtmlTest.php | 5 +++++ 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/samples/resources/Sample_30_ReadHTML.html b/samples/resources/Sample_30_ReadHTML.html index b3d2fad222..3ccbb5f204 100644 --- a/samples/resources/Sample_30_ReadHTML.html +++ b/samples/resources/Sample_30_ReadHTML.html @@ -17,9 +17,12 @@

        Adding element via HTML

        Includes images

        - - - +

        Nested p and i

        +

        + Contenido + B.O. de la Provincia de Barcelona + , 6-9-1939, citado en Díaz Plaja, F.: "España 1939-1979", +

        diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 58ce241288..f5a7e567bc 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -530,7 +530,7 @@ private static function parseStyle($attribute, $styles) $styles['bgColor'] = trim($cValue, '#'); break; case 'line-height': - if (preg_match('/([0-9]+[a-z]+)/', $cValue, $matches)) { + if (preg_match('/([0-9]+\.?[0-9]*[a-z]+)/', $cValue, $matches)) { $spacingLineRule = \PhpOffice\PhpWord\SimpleType\LineSpacingRule::EXACT; $spacing = Converter::cssToTwip($matches[1]) / \PhpOffice\PhpWord\Style\Paragraph::LINE_HEIGHT; } elseif (preg_match('/([0-9]+)%/', $cValue, $matches)) { diff --git a/tests/PhpWord/Shared/ConverterTest.php b/tests/PhpWord/Shared/ConverterTest.php index 3798a07b1d..fbe92c2593 100644 --- a/tests/PhpWord/Shared/ConverterTest.php +++ b/tests/PhpWord/Shared/ConverterTest.php @@ -126,6 +126,7 @@ public function testCssSizeParser() $this->assertEquals(10, Converter::cssToPoint('10pt')); $this->assertEquals(7.5, Converter::cssToPoint('10px')); $this->assertEquals(720, Converter::cssToPoint('10in')); + $this->assertEquals(7.2, Converter::cssToPoint('0.1in')); $this->assertEquals(120, Converter::cssToPoint('10pc')); $this->assertEquals(28.346457, Converter::cssToPoint('10mm'), '', 0.000001); $this->assertEquals(283.464567, Converter::cssToPoint('10cm'), '', 0.000001); diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index 481b5d75bc..ac273ad0a9 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -141,6 +141,7 @@ public function testParseLineHeight() Html::addHtml($section, '

        test

        '); Html::addHtml($section, '

        test

        '); Html::addHtml($section, '

        test

        '); + Html::addHtml($section, '

        test

        '); $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); $this->assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:pPr/w:spacing')); @@ -154,6 +155,10 @@ public function testParseLineHeight() $this->assertTrue($doc->elementExists('/w:document/w:body/w:p[3]/w:pPr/w:spacing')); $this->assertEquals(Paragraph::LINE_HEIGHT * 1.2, $doc->getElementAttribute('/w:document/w:body/w:p[3]/w:pPr/w:spacing', 'w:line')); $this->assertEquals(LineSpacingRule::AUTO, $doc->getElementAttribute('/w:document/w:body/w:p[3]/w:pPr/w:spacing', 'w:lineRule')); + + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p[4]/w:pPr/w:spacing')); + $this->assertEquals(244.8, $doc->getElementAttribute('/w:document/w:body/w:p[4]/w:pPr/w:spacing', 'w:line')); + $this->assertEquals(LineSpacingRule::EXACT, $doc->getElementAttribute('/w:document/w:body/w:p[4]/w:pPr/w:spacing', 'w:lineRule')); } /** From c93880b1250b06a73b557617f693c3cfd30dd59d Mon Sep 17 00:00:00 2001 From: Javier Garcia Date: Wed, 13 Jun 2018 18:14:13 +0200 Subject: [PATCH 120/135] clean sample resource --- samples/resources/Sample_30_ReadHTML.html | 7 ------- 1 file changed, 7 deletions(-) diff --git a/samples/resources/Sample_30_ReadHTML.html b/samples/resources/Sample_30_ReadHTML.html index 3ccbb5f204..0ff1a41432 100644 --- a/samples/resources/Sample_30_ReadHTML.html +++ b/samples/resources/Sample_30_ReadHTML.html @@ -17,12 +17,5 @@

        Adding element via HTML

        Includes images

        -

        Nested p and i

        -

        - Contenido - B.O. de la Provincia de Barcelona - , 6-9-1939, citado en Díaz Plaja, F.: "España 1939-1979", -

        - From 94cf1aecb6fa9dce566a4b88aeb282b33e9cc5b7 Mon Sep 17 00:00:00 2001 From: Jonathan Jefferies Date: Fri, 13 Jul 2018 23:12:34 +0100 Subject: [PATCH 121/135] Require `ext-zip` for development (#1419) * Require `ext-zip` for development * Require `ext-gd` for development --- composer.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/composer.json b/composer.json index dd3a2de857..9a14618e57 100644 --- a/composer.json +++ b/composer.json @@ -64,6 +64,8 @@ "phpoffice/common": "^0.2" }, "require-dev": { + "ext-zip": "*", + "ext-gd": "*", "phpunit/phpunit": "^4.8.36 || ^5.0", "squizlabs/php_codesniffer": "^2.9", "friendsofphp/php-cs-fixer": "^2.2", From 536a1b89d73c1f7a14322839cd5598eddb3d1cfc Mon Sep 17 00:00:00 2001 From: troosan Date: Sat, 14 Jul 2018 00:50:01 +0200 Subject: [PATCH 122/135] disable entity loader --- composer.json | 2 +- src/PhpWord/Shared/Html.php | 1 + src/PhpWord/TemplateProcessor.php | 1 + tests/PhpWord/_includes/XmlDocument.php | 2 ++ 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 9a14618e57..4bba86b32b 100644 --- a/composer.json +++ b/composer.json @@ -66,7 +66,7 @@ "require-dev": { "ext-zip": "*", "ext-gd": "*", - "phpunit/phpunit": "^4.8.36 || ^5.0", + "phpunit/phpunit": "^4.8.36 || ^7.0", "squizlabs/php_codesniffer": "^2.9", "friendsofphp/php-cs-fixer": "^2.2", "phpmd/phpmd": "2.*", diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 239cfd1dbb..a42816781a 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -71,6 +71,7 @@ public static function addHtml($element, $html, $fullHTML = false, $preserveWhit } // Load DOM + libxml_disable_entity_loader(true); $dom = new \DOMDocument(); $dom->preserveWhiteSpace = $preserveWhiteSpace; $dom->loadXML($html); diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index 72446ae744..946d66913a 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -113,6 +113,7 @@ public function __construct($documentTemplate) */ protected function transformSingleXml($xml, $xsltProcessor) { + libxml_disable_entity_loader(true); $domDocument = new \DOMDocument(); if (false === $domDocument->loadXML($xml)) { throw new Exception('Could not load the given XML document.'); diff --git a/tests/PhpWord/_includes/XmlDocument.php b/tests/PhpWord/_includes/XmlDocument.php index 8c937bf5a0..81de7eff20 100644 --- a/tests/PhpWord/_includes/XmlDocument.php +++ b/tests/PhpWord/_includes/XmlDocument.php @@ -76,8 +76,10 @@ public function getFileDom($file = 'word/document.xml') $this->file = $file; $file = $this->path . '/' . $file; + libxml_disable_entity_loader(false); $this->dom = new \DOMDocument(); $this->dom->load($file); + libxml_disable_entity_loader(true); return $this->dom; } From 96b21badaf99442f2a1de5a1b2298ae371d0e901 Mon Sep 17 00:00:00 2001 From: troosan Date: Sat, 14 Jul 2018 00:54:41 +0200 Subject: [PATCH 123/135] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cdd78870f2..d2b009dc42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ v0.15.0 (?? ??? 2018) - Fix parsing of Heading and Title formating @troosan @gthomas2 #465 - Fix Dateformat typo, fix hours casing, add Month-Day-Year formats @ComputerTinker #591 - Fix missing column width in ODText writer @potofcoffee #413 +- Disable entity loader before parsing XML to avoid XXE injection @Tom4t0 #1427 ### Changed - Remove zend-stdlib dependency @Trainmaster #1284 From 4c4c6f43ca446c0998f925f52b3b1aa3fe5289bb Mon Sep 17 00:00:00 2001 From: troosan Date: Sat, 14 Jul 2018 00:59:54 +0200 Subject: [PATCH 124/135] remove options not compatible with latest phpunit version --- phpunit.xml.dist | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 015dd2edd1..17fcfa3983 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -6,8 +6,7 @@ convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" - stopOnFailure="false" - syntaxCheck="false"> + stopOnFailure="false"> ./tests/PhpWord @@ -22,7 +21,7 @@ - + \ No newline at end of file From 3906be19ee92729a4e12bdbd499f031aae12bf03 Mon Sep 17 00:00:00 2001 From: smaug1985 Date: Sat, 14 Jul 2018 02:13:45 +0200 Subject: [PATCH 125/135] Added Support for Indentation & Tabs on RTF Writer. (#1405) * Added Support for Indentation & Tabs on RTF Writer. * add decimal tab writer + tests * Update CHANGELOG.md --- CHANGELOG.md | 1 + src/PhpWord/Writer/RTF/Style/Indentation.php | 45 ++++++++++++++++ src/PhpWord/Writer/RTF/Style/Paragraph.php | 40 ++++++++++++++ src/PhpWord/Writer/RTF/Style/Tab.php | 49 +++++++++++++++++ tests/PhpWord/Writer/RTF/StyleTest.php | 55 +++++++++++++++++++- 5 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 src/PhpWord/Writer/RTF/Style/Indentation.php create mode 100644 src/PhpWord/Writer/RTF/Style/Tab.php diff --git a/CHANGELOG.md b/CHANGELOG.md index d2b009dc42..03387b3714 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ v0.15.0 (?? ??? 2018) - Added parsing of internal links in HTML reader @lalop #1336 - Several improvements to charts @JAEK-S #1332 - Add parsing of html image in base64 format @jgpATs2w #1382 +- Added Support for Indentation & Tabs on RTF Writer. @smaug1985 #1405 ### Fixed - Fix reading of docx default style - @troosan #1238 diff --git a/src/PhpWord/Writer/RTF/Style/Indentation.php b/src/PhpWord/Writer/RTF/Style/Indentation.php new file mode 100644 index 0000000000..5c80af0cb6 --- /dev/null +++ b/src/PhpWord/Writer/RTF/Style/Indentation.php @@ -0,0 +1,45 @@ +getStyle(); + if (!$style instanceof \PhpOffice\PhpWord\Style\Indentation) { + return; + } + + $content = '\fi' . $style->getFirstLine(); + $content .= '\li' . $style->getLeft(); + $content .= '\ri' . $style->getRight(); + + return $content . ' '; + } +} diff --git a/src/PhpWord/Writer/RTF/Style/Paragraph.php b/src/PhpWord/Writer/RTF/Style/Paragraph.php index 3b8690cd4a..cb50a31b02 100644 --- a/src/PhpWord/Writer/RTF/Style/Paragraph.php +++ b/src/PhpWord/Writer/RTF/Style/Paragraph.php @@ -64,9 +64,49 @@ public function write() if (isset($alignments[$style->getAlignment()])) { $content .= $alignments[$style->getAlignment()]; } + $content .= $this->writeIndentation($style->getIndentation()); $content .= $this->getValueIf($spaceBefore !== null, '\sb' . $spaceBefore); $content .= $this->getValueIf($spaceAfter !== null, '\sa' . $spaceAfter); + $styles = $style->getStyleValues(); + $content .= $this->writeTabs($styles['tabs']); + + return $content; + } + + /** + * Writes an \PhpOffice\PhpWord\Style\Indentation + * + * @param null|\PhpOffice\PhpWord\Style\Indentation $indent + * @return string + */ + private function writeIndentation($indent = null) + { + if (isset($indent) && $indent instanceof \PhpOffice\PhpWord\Style\Indentation) { + $writer = new Indentation($indent); + + return $writer->write(); + } + + return ''; + } + + /** + * Writes tabs + * + * @param \PhpOffice\PhpWord\Style\Tab[] $tabs + * @return string + */ + private function writeTabs($tabs = null) + { + $content = ''; + if (!empty($tabs)) { + foreach ($tabs as $tab) { + $styleWriter = new Tab($tab); + $content .= $styleWriter->write(); + } + } + return $content; } diff --git a/src/PhpWord/Writer/RTF/Style/Tab.php b/src/PhpWord/Writer/RTF/Style/Tab.php new file mode 100644 index 0000000000..fe1f9363eb --- /dev/null +++ b/src/PhpWord/Writer/RTF/Style/Tab.php @@ -0,0 +1,49 @@ +getStyle(); + if (!$style instanceof \PhpOffice\PhpWord\Style\Tab) { + return; + } + $tabs = array( + \PhpOffice\PhpWord\Style\Tab::TAB_STOP_RIGHT => '\tqr', + \PhpOffice\PhpWord\Style\Tab::TAB_STOP_CENTER => '\tqc', + \PhpOffice\PhpWord\Style\Tab::TAB_STOP_DECIMAL => '\tqdec', + ); + $content = ''; + if (isset($tabs[$style->getType()])) { + $content .= $tabs[$style->getType()]; + } + $content .= '\tx' . $style->getPosition(); + + return $content; + } +} diff --git a/tests/PhpWord/Writer/RTF/StyleTest.php b/tests/PhpWord/Writer/RTF/StyleTest.php index 5f04f1a815..317014c610 100644 --- a/tests/PhpWord/Writer/RTF/StyleTest.php +++ b/tests/PhpWord/Writer/RTF/StyleTest.php @@ -17,7 +17,9 @@ namespace PhpOffice\PhpWord\Writer\RTF; +use PhpOffice\PhpWord\Writer\RTF; use PhpOffice\PhpWord\Writer\RTF\Style\Border; +use PHPUnit\Framework\Assert; /** * Test class for PhpOffice\PhpWord\Writer\RTF\Style subnamespace @@ -29,7 +31,7 @@ class StyleTest extends \PHPUnit\Framework\TestCase */ public function testEmptyStyles() { - $styles = array('Font', 'Paragraph', 'Section'); + $styles = array('Font', 'Paragraph', 'Section', 'Tab', 'Indentation'); foreach ($styles as $style) { $objectClass = 'PhpOffice\\PhpWord\\Writer\\RTF\\Style\\' . $style; $object = new $objectClass(); @@ -55,4 +57,55 @@ public function testBorderWithNonRegisteredColors() $this->assertEquals($expected, $content); } + + public function testIndentation() + { + $indentation = new \PhpOffice\PhpWord\Style\Indentation(); + $indentation->setLeft(1); + $indentation->setRight(2); + $indentation->setFirstLine(3); + + $indentWriter = new \PhpOffice\PhpWord\Writer\RTF\Style\Indentation($indentation); + $indentWriter->setParentWriter(new RTF()); + $result = $indentWriter->write(); + + Assert::assertEquals('\fi3\li1\ri2 ', $result); + } + + public function testRightTab() + { + $tabRight = new \PhpOffice\PhpWord\Style\Tab(); + $tabRight->setType(\PhpOffice\PhpWord\Style\Tab::TAB_STOP_RIGHT); + $tabRight->setPosition(5); + + $tabWriter = new \PhpOffice\PhpWord\Writer\RTF\Style\Tab($tabRight); + $tabWriter->setParentWriter(new RTF()); + $result = $tabWriter->write(); + + Assert::assertEquals('\tqr\tx5', $result); + } + + public function testCenterTab() + { + $tabRight = new \PhpOffice\PhpWord\Style\Tab(); + $tabRight->setType(\PhpOffice\PhpWord\Style\Tab::TAB_STOP_CENTER); + + $tabWriter = new \PhpOffice\PhpWord\Writer\RTF\Style\Tab($tabRight); + $tabWriter->setParentWriter(new RTF()); + $result = $tabWriter->write(); + + Assert::assertEquals('\tqc\tx0', $result); + } + + public function testDecimalTab() + { + $tabRight = new \PhpOffice\PhpWord\Style\Tab(); + $tabRight->setType(\PhpOffice\PhpWord\Style\Tab::TAB_STOP_DECIMAL); + + $tabWriter = new \PhpOffice\PhpWord\Writer\RTF\Style\Tab($tabRight); + $tabWriter->setParentWriter(new RTF()); + $result = $tabWriter->write(); + + Assert::assertEquals('\tqdec\tx0', $result); + } } From e028aef6d2cb6dd27a24be6334c14c38f5849dbc Mon Sep 17 00:00:00 2001 From: troosan Date: Sat, 14 Jul 2018 02:26:47 +0200 Subject: [PATCH 126/135] update to final phpoffice/common version --- CHANGELOG.md | 1 + composer.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0b39ce1be..1f1e194b65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ v0.15.0 (?? ??? 2018) - Fix colspan and rowspan for tables in HTML Writer @mattbolt #1292 - Fix parsing of Heading and Title formating @troosan @gthomas2 #465 - Fix Dateformat typo, fix hours casing, add Month-Day-Year formats @ComputerTinker #591 +- Support reading of w:drawing for documents produced by word 2011+ @gthomas2 #464 #1324 ### Changed - Remove zend-stdlib dependency @Trainmaster #1284 diff --git a/composer.json b/composer.json index 6dc9be2c68..1844e82e01 100644 --- a/composer.json +++ b/composer.json @@ -61,7 +61,7 @@ "php": "^5.3.3 || ^7.0", "ext-xml": "*", "zendframework/zend-escaper": "^2.2", - "phpoffice/common": "dev-develop" + "phpoffice/common": "^0.2.9" }, "require-dev": { "phpunit/phpunit": "^4.8.36 || ^5.0", From adc1428607d73018ec0d088196953e99c9045c58 Mon Sep 17 00:00:00 2001 From: troosan Date: Sat, 14 Jul 2018 02:51:08 +0200 Subject: [PATCH 127/135] use PasswordEncoder from phpoffice/common instead --- src/PhpWord/Metadata/Protection.php | 2 +- .../Shared/Microsoft/PasswordEncoder.php | 235 ------------------ src/PhpWord/Writer/Word2007/Part/Settings.php | 2 +- .../Shared/Microsoft/PasswordEncoderTest.php | 91 ------- .../Writer/Word2007/Part/SettingsTest.php | 2 +- 5 files changed, 3 insertions(+), 329 deletions(-) delete mode 100644 src/PhpWord/Shared/Microsoft/PasswordEncoder.php delete mode 100644 tests/PhpWord/Shared/Microsoft/PasswordEncoderTest.php diff --git a/src/PhpWord/Metadata/Protection.php b/src/PhpWord/Metadata/Protection.php index 584ed83e43..197f80221c 100644 --- a/src/PhpWord/Metadata/Protection.php +++ b/src/PhpWord/Metadata/Protection.php @@ -17,7 +17,7 @@ namespace PhpOffice\PhpWord\Metadata; -use PhpOffice\PhpWord\Shared\Microsoft\PasswordEncoder; +use PhpOffice\Common\Microsoft\PasswordEncoder; use PhpOffice\PhpWord\SimpleType\DocProtect; /** diff --git a/src/PhpWord/Shared/Microsoft/PasswordEncoder.php b/src/PhpWord/Shared/Microsoft/PasswordEncoder.php deleted file mode 100644 index fc0c7ecdf8..0000000000 --- a/src/PhpWord/Shared/Microsoft/PasswordEncoder.php +++ /dev/null @@ -1,235 +0,0 @@ - array(1, 'md2'), - self::ALGORITHM_MD4 => array(2, 'md4'), - self::ALGORITHM_MD5 => array(3, 'md5'), - self::ALGORITHM_SHA_1 => array(4, 'sha1'), - self::ALGORITHM_MAC => array(5, ''), // 'mac' -> not possible with hash() - self::ALGORITHM_RIPEMD => array(6, 'ripemd'), - self::ALGORITHM_RIPEMD_160 => array(7, 'ripemd160'), - self::ALGORITHM_HMAC => array(9, ''), //'hmac' -> not possible with hash() - self::ALGORITHM_SHA_256 => array(12, 'sha256'), - self::ALGORITHM_SHA_384 => array(13, 'sha384'), - self::ALGORITHM_SHA_512 => array(14, 'sha512'), - ); - - private static $initialCodeArray = array( - 0xE1F0, - 0x1D0F, - 0xCC9C, - 0x84C0, - 0x110C, - 0x0E10, - 0xF1CE, - 0x313E, - 0x1872, - 0xE139, - 0xD40F, - 0x84F9, - 0x280C, - 0xA96A, - 0x4EC3, - ); - - private static $encryptionMatrix = array( - array(0xAEFC, 0x4DD9, 0x9BB2, 0x2745, 0x4E8A, 0x9D14, 0x2A09), - array(0x7B61, 0xF6C2, 0xFDA5, 0xEB6B, 0xC6F7, 0x9DCF, 0x2BBF), - array(0x4563, 0x8AC6, 0x05AD, 0x0B5A, 0x16B4, 0x2D68, 0x5AD0), - array(0x0375, 0x06EA, 0x0DD4, 0x1BA8, 0x3750, 0x6EA0, 0xDD40), - array(0xD849, 0xA0B3, 0x5147, 0xA28E, 0x553D, 0xAA7A, 0x44D5), - array(0x6F45, 0xDE8A, 0xAD35, 0x4A4B, 0x9496, 0x390D, 0x721A), - array(0xEB23, 0xC667, 0x9CEF, 0x29FF, 0x53FE, 0xA7FC, 0x5FD9), - array(0x47D3, 0x8FA6, 0x0F6D, 0x1EDA, 0x3DB4, 0x7B68, 0xF6D0), - array(0xB861, 0x60E3, 0xC1C6, 0x93AD, 0x377B, 0x6EF6, 0xDDEC), - array(0x45A0, 0x8B40, 0x06A1, 0x0D42, 0x1A84, 0x3508, 0x6A10), - array(0xAA51, 0x4483, 0x8906, 0x022D, 0x045A, 0x08B4, 0x1168), - array(0x76B4, 0xED68, 0xCAF1, 0x85C3, 0x1BA7, 0x374E, 0x6E9C), - array(0x3730, 0x6E60, 0xDCC0, 0xA9A1, 0x4363, 0x86C6, 0x1DAD), - array(0x3331, 0x6662, 0xCCC4, 0x89A9, 0x0373, 0x06E6, 0x0DCC), - array(0x1021, 0x2042, 0x4084, 0x8108, 0x1231, 0x2462, 0x48C4), - ); - - private static $passwordMaxLength = 15; - - /** - * Create a hashed password that MS Word will be able to work with - * @see https://blogs.msdn.microsoft.com/vsod/2010/04/05/how-to-set-the-editing-restrictions-in-word-using-open-xml-sdk-2-0/ - * - * @param string $password - * @param string $algorithmName - * @param string $salt - * @param int $spinCount - * @return string - */ - public static function hashPassword($password, $algorithmName = self::ALGORITHM_SHA_1, $salt = null, $spinCount = 10000) - { - $origEncoding = mb_internal_encoding(); - mb_internal_encoding('UTF-8'); - - $password = mb_substr($password, 0, min(self::$passwordMaxLength, mb_strlen($password))); - - // Get the single-byte values by iterating through the Unicode characters of the truncated password. - // For each character, if the low byte is not equal to 0, take it. Otherwise, take the high byte. - $passUtf8 = mb_convert_encoding($password, 'UCS-2LE', 'UTF-8'); - $byteChars = array(); - - for ($i = 0; $i < mb_strlen($password); $i++) { - $byteChars[$i] = ord(substr($passUtf8, $i * 2, 1)); - - if ($byteChars[$i] == 0) { - $byteChars[$i] = ord(substr($passUtf8, $i * 2 + 1, 1)); - } - } - - // build low-order word and hig-order word and combine them - $combinedKey = self::buildCombinedKey($byteChars); - // build reversed hexadecimal string - $hex = str_pad(strtoupper(dechex($combinedKey & 0xFFFFFFFF)), 8, '0', \STR_PAD_LEFT); - $reversedHex = $hex[6] . $hex[7] . $hex[4] . $hex[5] . $hex[2] . $hex[3] . $hex[0] . $hex[1]; - - $generatedKey = mb_convert_encoding($reversedHex, 'UCS-2LE', 'UTF-8'); - - // Implementation Notes List: - // Word requires that the initial hash of the password with the salt not be considered in the count. - // The initial hash of salt + key is not included in the iteration count. - $algorithm = self::getAlgorithm($algorithmName); - $generatedKey = hash($algorithm, $salt . $generatedKey, true); - - for ($i = 0; $i < $spinCount; $i++) { - $generatedKey = hash($algorithm, $generatedKey . pack('CCCC', $i, $i >> 8, $i >> 16, $i >> 24), true); - } - $generatedKey = base64_encode($generatedKey); - - mb_internal_encoding($origEncoding); - - return $generatedKey; - } - - /** - * Get algorithm from self::$algorithmMapping - * - * @param string $algorithmName - * @return string - */ - private static function getAlgorithm($algorithmName) - { - $algorithm = self::$algorithmMapping[$algorithmName][1]; - if ($algorithm == '') { - $algorithm = 'sha1'; - } - - return $algorithm; - } - - /** - * Returns the algorithm ID - * - * @param string $algorithmName - * @return int - */ - public static function getAlgorithmId($algorithmName) - { - return self::$algorithmMapping[$algorithmName][0]; - } - - /** - * Build combined key from low-order word and high-order word - * - * @param array $byteChars byte array representation of password - * @return int - */ - private static function buildCombinedKey($byteChars) - { - $byteCharsLength = count($byteChars); - // Compute the high-order word - // Initialize from the initial code array (see above), depending on the passwords length. - $highOrderWord = self::$initialCodeArray[$byteCharsLength - 1]; - - // For each character in the password: - // For every bit in the character, starting with the least significant and progressing to (but excluding) - // the most significant, if the bit is set, XOR the key’s high-order word with the corresponding word from - // the Encryption Matrix - for ($i = 0; $i < $byteCharsLength; $i++) { - $tmp = self::$passwordMaxLength - $byteCharsLength + $i; - $matrixRow = self::$encryptionMatrix[$tmp]; - for ($intBit = 0; $intBit < 7; $intBit++) { - if (($byteChars[$i] & (0x0001 << $intBit)) != 0) { - $highOrderWord = ($highOrderWord ^ $matrixRow[$intBit]); - } - } - } - - // Compute low-order word - // Initialize with 0 - $lowOrderWord = 0; - // For each character in the password, going backwards - for ($i = $byteCharsLength - 1; $i >= 0; $i--) { - // low-order word = (((low-order word SHR 14) AND 0x0001) OR (low-order word SHL 1) AND 0x7FFF)) XOR character - $lowOrderWord = (((($lowOrderWord >> 14) & 0x0001) | (($lowOrderWord << 1) & 0x7FFF)) ^ $byteChars[$i]); - } - // Lastly, low-order word = (((low-order word SHR 14) AND 0x0001) OR (low-order word SHL 1) AND 0x7FFF)) XOR strPassword length XOR 0xCE4B. - $lowOrderWord = (((($lowOrderWord >> 14) & 0x0001) | (($lowOrderWord << 1) & 0x7FFF)) ^ $byteCharsLength ^ 0xCE4B); - - // Combine the Low and High Order Word - return self::int32(($highOrderWord << 16) + $lowOrderWord); - } - - /** - * Simulate behaviour of (signed) int32 - * - * @codeCoverageIgnore - * @param int $value - * @return int - */ - private static function int32($value) - { - $value = ($value & 0xFFFFFFFF); - - if ($value & 0x80000000) { - $value = -((~$value & 0xFFFFFFFF) + 1); - } - - return $value; - } -} diff --git a/src/PhpWord/Writer/Word2007/Part/Settings.php b/src/PhpWord/Writer/Word2007/Part/Settings.php index 42d3a5d5ff..b764642a6a 100644 --- a/src/PhpWord/Writer/Word2007/Part/Settings.php +++ b/src/PhpWord/Writer/Word2007/Part/Settings.php @@ -17,9 +17,9 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Part; +use PhpOffice\Common\Microsoft\PasswordEncoder; use PhpOffice\PhpWord\ComplexType\ProofState; use PhpOffice\PhpWord\ComplexType\TrackChangesView; -use PhpOffice\PhpWord\Shared\Microsoft\PasswordEncoder; use PhpOffice\PhpWord\Style\Language; /** diff --git a/tests/PhpWord/Shared/Microsoft/PasswordEncoderTest.php b/tests/PhpWord/Shared/Microsoft/PasswordEncoderTest.php deleted file mode 100644 index 5a050c54e5..0000000000 --- a/tests/PhpWord/Shared/Microsoft/PasswordEncoderTest.php +++ /dev/null @@ -1,91 +0,0 @@ - Date: Sat, 14 Jul 2018 02:54:17 +0200 Subject: [PATCH 128/135] fix phpstan issues --- phpstan.neon | 2 +- src/PhpWord/Element/Title.php | 14 ++++++-------- src/PhpWord/Shared/Html.php | 2 +- src/PhpWord/Writer/Word2007/Element/Title.php | 1 + src/PhpWord/Writer/Word2007/Part/Chart.php | 4 ++-- tests/PhpWord/Writer/HTML/ElementTest.php | 6 +++--- tests/PhpWord/_includes/XmlDocument.php | 6 +++--- 7 files changed, 17 insertions(+), 18 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index 5ae6d0f28a..666c63b9c1 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,7 +1,7 @@ includes: - vendor/phpstan/phpstan/conf/config.level1.neon parameters: - memory-limit: 200000 + memory-limit: 20000000 autoload_directories: - tests autoload_files: diff --git a/src/PhpWord/Element/Title.php b/src/PhpWord/Element/Title.php index 569cea925c..eb261b1f0e 100644 --- a/src/PhpWord/Element/Title.php +++ b/src/PhpWord/Element/Title.php @@ -61,14 +61,12 @@ class Title extends AbstractElement */ public function __construct($text, $depth = 1) { - if (isset($text)) { - if (is_string($text)) { - $this->text = CommonText::toUTF8($text); - } elseif ($text instanceof TextRun) { - $this->text = $text; - } else { - throw new \InvalidArgumentException('Invalid text, should be a string or a TextRun'); - } + if (is_string($text)) { + $this->text = CommonText::toUTF8($text); + } elseif ($text instanceof TextRun) { + $this->text = $text; + } else { + throw new \InvalidArgumentException('Invalid text, should be a string or a TextRun'); } $this->depth = $depth; diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index a42816781a..f725c366a0 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -75,7 +75,7 @@ public static function addHtml($element, $html, $fullHTML = false, $preserveWhit $dom = new \DOMDocument(); $dom->preserveWhiteSpace = $preserveWhiteSpace; $dom->loadXML($html); - self::$xpath = new \DOMXpath($dom); + self::$xpath = new \DOMXPath($dom); $node = $dom->getElementsByTagName('body'); self::parseNode($node->item(0), $element); diff --git a/src/PhpWord/Writer/Word2007/Element/Title.php b/src/PhpWord/Writer/Word2007/Element/Title.php index 858ecfefa7..6a05a34d6f 100644 --- a/src/PhpWord/Writer/Word2007/Element/Title.php +++ b/src/PhpWord/Writer/Word2007/Element/Title.php @@ -47,6 +47,7 @@ public function write() $xmlWriter->endElement(); } + $bookmarkRId = null; if ($element->getDepth() !== 0) { $rId = $element->getRelationId(); $bookmarkRId = $element->getPhpWord()->addBookmark(); diff --git a/src/PhpWord/Writer/Word2007/Part/Chart.php b/src/PhpWord/Writer/Word2007/Part/Chart.php index 17c1fd54ac..5a3ef27678 100644 --- a/src/PhpWord/Writer/Word2007/Part/Chart.php +++ b/src/PhpWord/Writer/Word2007/Part/Chart.php @@ -330,11 +330,11 @@ private function writeAxis(XMLWriter $xmlWriter, $type) $valueAxisTitle = $style->getValueAxisTitle(); if ($axisType == 'c:catAx') { - if (isset($categoryAxisTitle)) { + if (!is_null($categoryAxisTitle)) { $this->writeAxisTitle($xmlWriter, $categoryAxisTitle); } } elseif ($axisType == 'c:valAx') { - if (isset($valueAxisTitle)) { + if (!is_null($valueAxisTitle)) { $this->writeAxisTitle($xmlWriter, $valueAxisTitle); } } diff --git a/tests/PhpWord/Writer/HTML/ElementTest.php b/tests/PhpWord/Writer/HTML/ElementTest.php index 90044b9293..b76ddded5d 100644 --- a/tests/PhpWord/Writer/HTML/ElementTest.php +++ b/tests/PhpWord/Writer/HTML/ElementTest.php @@ -70,7 +70,7 @@ public function testWriteTrackChanges() $text2->setTrackChange(new TrackChange(TrackChange::DELETED, 'another author', new \DateTime())); $dom = $this->getAsHTML($phpWord); - $xpath = new \DOMXpath($dom); + $xpath = new \DOMXPath($dom); $this->assertTrue($xpath->query('/html/body/p[1]/ins')->length == 1); $this->assertTrue($xpath->query('/html/body/p[2]/del')->length == 1); @@ -94,7 +94,7 @@ public function testWriteColSpan() $cell22->addText('second cell'); $dom = $this->getAsHTML($phpWord); - $xpath = new \DOMXpath($dom); + $xpath = new \DOMXPath($dom); $this->assertTrue($xpath->query('/html/body/table/tr[1]/td')->length == 1); $this->assertEquals('2', $xpath->query('/html/body/table/tr/td[1]')->item(0)->attributes->getNamedItem('colspan')->textContent); @@ -123,7 +123,7 @@ public function testWriteRowSpan() $row3->addCell(500)->addText('third cell being spanned'); $dom = $this->getAsHTML($phpWord); - $xpath = new \DOMXpath($dom); + $xpath = new \DOMXPath($dom); $this->assertTrue($xpath->query('/html/body/table/tr[1]/td')->length == 2); $this->assertEquals('3', $xpath->query('/html/body/table/tr[1]/td[1]')->item(0)->attributes->getNamedItem('rowspan')->textContent); diff --git a/tests/PhpWord/_includes/XmlDocument.php b/tests/PhpWord/_includes/XmlDocument.php index 81de7eff20..7062ebbf0b 100644 --- a/tests/PhpWord/_includes/XmlDocument.php +++ b/tests/PhpWord/_includes/XmlDocument.php @@ -37,9 +37,9 @@ class XmlDocument private $dom; /** - * DOMXpath object + * DOMXPath object * - * @var \DOMXpath + * @var \DOMXPath */ private $xpath; @@ -98,7 +98,7 @@ public function getNodeList($path, $file = 'word/document.xml') } if (null === $this->xpath) { - $this->xpath = new \DOMXpath($this->dom); + $this->xpath = new \DOMXPath($this->dom); $this->xpath->registerNamespace('w14', 'http://schemas.microsoft.com/office/word/2010/wordml'); } From 6475812e828be030a39adc8c8d9a925bd9d163b7 Mon Sep 17 00:00:00 2001 From: troosan Date: Sat, 14 Jul 2018 03:28:09 +0200 Subject: [PATCH 129/135] fix documentation --- src/PhpWord/Element/OLEObject.php | 2 +- src/PhpWord/Element/PreserveText.php | 6 ++---- src/PhpWord/Element/Title.php | 2 -- src/PhpWord/Metadata/Protection.php | 6 +++--- src/PhpWord/Reader/Word2007/Settings.php | 10 +++++----- src/PhpWord/Writer/RTF/Style/Indentation.php | 2 +- 6 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/PhpWord/Element/OLEObject.php b/src/PhpWord/Element/OLEObject.php index c0c7f21798..1a17b74753 100644 --- a/src/PhpWord/Element/OLEObject.php +++ b/src/PhpWord/Element/OLEObject.php @@ -83,7 +83,7 @@ public function __construct($source, $style = null) $this->style = $this->setNewStyle(new ImageStyle(), $style, true); $this->icon = realpath(__DIR__ . "/../resources/{$ext}.png"); - return $this; + return; } throw new InvalidObjectException(); diff --git a/src/PhpWord/Element/PreserveText.php b/src/PhpWord/Element/PreserveText.php index 1ce2dcdd78..374f1a9984 100644 --- a/src/PhpWord/Element/PreserveText.php +++ b/src/PhpWord/Element/PreserveText.php @@ -29,7 +29,7 @@ class PreserveText extends AbstractElement /** * Text content * - * @var string + * @var string|array */ private $text; @@ -64,8 +64,6 @@ public function __construct($text = null, $fontStyle = null, $paragraphStyle = n if (isset($matches[0])) { $this->text = $matches; } - - return $this; } /** @@ -91,7 +89,7 @@ public function getParagraphStyle() /** * Get Text content * - * @return string + * @return string|array */ public function getText() { diff --git a/src/PhpWord/Element/Title.php b/src/PhpWord/Element/Title.php index eb261b1f0e..d01f7f339d 100644 --- a/src/PhpWord/Element/Title.php +++ b/src/PhpWord/Element/Title.php @@ -74,8 +74,6 @@ public function __construct($text, $depth = 1) if (array_key_exists($styleName, Style::getStyles())) { $this->style = str_replace('_', '', $styleName); } - - return $this; } /** diff --git a/src/PhpWord/Metadata/Protection.php b/src/PhpWord/Metadata/Protection.php index 197f80221c..15aa3ff189 100644 --- a/src/PhpWord/Metadata/Protection.php +++ b/src/PhpWord/Metadata/Protection.php @@ -113,7 +113,7 @@ public function getPassword() /** * Set password * - * @param $password + * @param string $password * @return self */ public function setPassword($password) @@ -136,7 +136,7 @@ public function getSpinCount() /** * Set count for hash iterations * - * @param $spinCount + * @param int $spinCount * @return self */ public function setSpinCount($spinCount) @@ -159,7 +159,7 @@ public function getAlgorithm() /** * Set algorithm * - * @param $algorithm + * @param string $algorithm * @return self */ public function setAlgorithm($algorithm) diff --git a/src/PhpWord/Reader/Word2007/Settings.php b/src/PhpWord/Reader/Word2007/Settings.php index dbf3462335..3084943b37 100644 --- a/src/PhpWord/Reader/Word2007/Settings.php +++ b/src/PhpWord/Reader/Word2007/Settings.php @@ -81,7 +81,7 @@ public function read(PhpWord $phpWord) * * @param XMLReader $xmlReader * @param PhpWord $phpWord - * @param \DOMNode $node + * @param \DOMElement $node */ protected function setThemeFontLang(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node) { @@ -102,7 +102,7 @@ protected function setThemeFontLang(XMLReader $xmlReader, PhpWord $phpWord, \DOM * * @param XMLReader $xmlReader * @param PhpWord $phpWord - * @param \DOMNode $node + * @param \DOMElement $node */ protected function setDocumentProtection(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node) { @@ -119,7 +119,7 @@ protected function setDocumentProtection(XMLReader $xmlReader, PhpWord $phpWord, * * @param XMLReader $xmlReader * @param PhpWord $phpWord - * @param \DOMNode $node + * @param \DOMElement $node */ protected function setProofState(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node) { @@ -141,7 +141,7 @@ protected function setProofState(XMLReader $xmlReader, PhpWord $phpWord, \DOMEle * * @param XMLReader $xmlReader * @param PhpWord $phpWord - * @param \DOMNode $node + * @param \DOMElement $node */ protected function setZoom(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node) { @@ -158,7 +158,7 @@ protected function setZoom(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $ * * @param XMLReader $xmlReader * @param PhpWord $phpWord - * @param \DOMNode $node + * @param \DOMElement $node */ protected function setRevisionView(XMLReader $xmlReader, PhpWord $phpWord, \DOMElement $node) { diff --git a/src/PhpWord/Writer/RTF/Style/Indentation.php b/src/PhpWord/Writer/RTF/Style/Indentation.php index 5c80af0cb6..dd52230ee8 100644 --- a/src/PhpWord/Writer/RTF/Style/Indentation.php +++ b/src/PhpWord/Writer/RTF/Style/Indentation.php @@ -33,7 +33,7 @@ public function write() { $style = $this->getStyle(); if (!$style instanceof \PhpOffice\PhpWord\Style\Indentation) { - return; + return ''; } $content = '\fi' . $style->getFirstLine(); From 54155bf5a99102378f7c399ea60f898fa2abeeff Mon Sep 17 00:00:00 2001 From: troosan Date: Sat, 14 Jul 2018 17:16:24 +0200 Subject: [PATCH 130/135] Update Sample_30_ReadHTML.html --- samples/resources/Sample_30_ReadHTML.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/samples/resources/Sample_30_ReadHTML.html b/samples/resources/Sample_30_ReadHTML.html index 0ff1a41432..b3d2fad222 100644 --- a/samples/resources/Sample_30_ReadHTML.html +++ b/samples/resources/Sample_30_ReadHTML.html @@ -17,5 +17,9 @@

        Adding element via HTML

        Includes images

        + + + + From 87498e43e18f31e3161256ac0f70092c86718914 Mon Sep 17 00:00:00 2001 From: troosan Date: Sat, 14 Jul 2018 17:21:30 +0200 Subject: [PATCH 131/135] Allow passing short lang code --- CHANGELOG.md | 3 ++- src/PhpWord/Style/Language.php | 17 ++++++++++------- tests/PhpWord/Style/LanguageTest.php | 15 +++++++++++++++ 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 03387b3714..56a1d9ad20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ Change Log All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). -v0.15.0 (?? ??? 2018) +v0.15.0 (14 Jul 2018) ---------------------- ### Added - Parsing of `align` HTML attribute - @troosan #1231 @@ -25,6 +25,7 @@ v0.15.0 (?? ??? 2018) - Several improvements to charts @JAEK-S #1332 - Add parsing of html image in base64 format @jgpATs2w #1382 - Added Support for Indentation & Tabs on RTF Writer. @smaug1985 #1405 +- Allows decimal numbers in HTML line-height style @jgpATs2w #1413 ### Fixed - Fix reading of docx default style - @troosan #1238 diff --git a/src/PhpWord/Style/Language.php b/src/PhpWord/Style/Language.php index 4a50a59560..d7a76f78f3 100644 --- a/src/PhpWord/Style/Language.php +++ b/src/PhpWord/Style/Language.php @@ -123,8 +123,7 @@ public function __construct($latin = null, $eastAsia = null, $bidirectional = nu */ public function setLatin($latin) { - $this->validateLocale($latin); - $this->latin = $latin; + $this->latin = $this->validateLocale($latin); return $this; } @@ -173,8 +172,7 @@ public function getLangId() */ public function setEastAsia($eastAsia) { - $this->validateLocale($eastAsia); - $this->eastAsia = $eastAsia; + $this->eastAsia = $this->validateLocale($eastAsia); return $this; } @@ -198,8 +196,7 @@ public function getEastAsia() */ public function setBidirectional($bidirectional) { - $this->validateLocale($bidirectional); - $this->bidirectional = $bidirectional; + $this->bidirectional = $this->validateLocale($bidirectional); return $this; } @@ -218,12 +215,18 @@ public function getBidirectional() * Validates that the language passed is in the format xx-xx * * @param string $locale - * @return bool + * @return string */ private function validateLocale($locale) { + if (strlen($locale) === 2) { + return strtolower($locale) . '-' . strtoupper($locale); + } + if ($locale !== null && strstr($locale, '-') === false) { throw new \InvalidArgumentException($locale . ' is not a valid language code'); } + + return $locale; } } diff --git a/tests/PhpWord/Style/LanguageTest.php b/tests/PhpWord/Style/LanguageTest.php index 99741cea51..3bf516f8ae 100644 --- a/tests/PhpWord/Style/LanguageTest.php +++ b/tests/PhpWord/Style/LanguageTest.php @@ -17,6 +17,8 @@ namespace PhpOffice\PhpWord\Style; +use PHPUnit\Framework\Assert; + /** * Test class for PhpOffice\PhpWord\Style\Language * @@ -56,7 +58,20 @@ public function testGetSetProperties() */ public function testWrongLanguage() { + $language = new Language(); + $language->setLatin('fra'); + } + + /** + * Tests that a language can be set with just a 2 char code + */ + public function testShortLanguage() + { + //when $language = new Language(); $language->setLatin('fr'); + + //then + Assert::assertEquals('fr-FR', $language->getLatin()); } } From 8fa1d4f2244c081ee009b16dddf9a69296c8adfe Mon Sep 17 00:00:00 2001 From: troosan Date: Sat, 14 Jul 2018 17:47:34 +0200 Subject: [PATCH 132/135] run checks with php 7.0 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c72dd8c298..db77ff0598 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ php: matrix: include: - - php: 5.6 + - php: 7.0 env: COVERAGE=1 cache: From 4c9e75088a9f0794ec038d1f4cfccc268cdaea08 Mon Sep 17 00:00:00 2001 From: troosan Date: Sat, 14 Jul 2018 18:36:29 +0200 Subject: [PATCH 133/135] alias for develop branch [ci skip] --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 9f0e8a43e5..5d8a855b53 100644 --- a/composer.json +++ b/composer.json @@ -90,7 +90,7 @@ }, "extra": { "branch-alias": { - "dev-develop": "0.15-dev" + "dev-develop": "0.16-dev" } } } From e07c6559a9d1bdac676f00e2c290cb2c99e1a7e0 Mon Sep 17 00:00:00 2001 From: troosan Date: Thu, 19 Jul 2018 00:52:22 +0200 Subject: [PATCH 134/135] adapt test --- tests/PhpWord/TemplateProcessorTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/PhpWord/TemplateProcessorTest.php b/tests/PhpWord/TemplateProcessorTest.php index 770428cb69..ea7395610d 100644 --- a/tests/PhpWord/TemplateProcessorTest.php +++ b/tests/PhpWord/TemplateProcessorTest.php @@ -260,6 +260,7 @@ public function cloneBlockCanCloneABlockTwice() // and the placeholders have been replaced correctly $phpWord = IOFactory::load($templatePath); $sections = $phpWord->getSections(); + /** @var \PhpOffice\PhpWord\Element\TextRun[] $actualElements */ $actualElements = $sections[0]->getElements(); unlink($templatePath); $expectedElements = array( @@ -271,7 +272,7 @@ public function cloneBlockCanCloneABlockTwice() foreach ($expectedElements as $i => $expectedElement) { $this->assertEquals( $expectedElement, - $actualElements[$i]->getText() + $actualElements[$i]->getElement(0)->getText() ); } } From 1951db58c18e6a0492db5a1b46dd5963c12b052f Mon Sep 17 00:00:00 2001 From: troosan Date: Thu, 19 Jul 2018 01:16:25 +0200 Subject: [PATCH 135/135] update changelog --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a166345cba..d822357cbd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,13 @@ Change Log All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +v0.16.0 (xx xxx 2018) +---------------------- +### Added + +### Fixed +- Fix regex in `cloneBlock` function @nicoder #1269 + v0.15.0 (14 Jul 2018) ---------------------- ### Added