From 62d3f97e30a5b7262c6655c9a87686254daf5793 Mon Sep 17 00:00:00 2001 From: Frank Meyer Date: Tue, 21 Jul 2015 14:07:23 +0200 Subject: [PATCH 001/148] 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 bc18392e..b6830fa0 100644 --- a/samples/Sample_32_Chart.php +++ b/samples/Sample_32_Chart.php @@ -22,11 +22,16 @@ $categories = array('A', 'B', 'C', 'D', 'E'); $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 @@ $section = $phpWord->addSection(array('colsNum' => 2, 'breakType' => 'continuous $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 13b72a33..112a0a4a 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 @@ class Chart extends AbstractStyle 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 8423762c..abc2962a 100644 --- a/src/PhpWord/Writer/Word2007/Part/Chart.php +++ b/src/PhpWord/Writer/Word2007/Part/Chart.php @@ -264,6 +264,7 @@ class Chart extends AbstractPart */ 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 @@ class Chart extends AbstractPart $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 @@ class Chart extends AbstractPart $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/148] 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 abc2962a..56df1027 100644 --- a/src/PhpWord/Writer/Word2007/Part/Chart.php +++ b/src/PhpWord/Writer/Word2007/Part/Chart.php @@ -274,7 +274,7 @@ class Chart extends AbstractPart $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 @@ class Chart extends AbstractPart $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/148] 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 56df1027..92d61e6e 100644 --- a/src/PhpWord/Writer/Word2007/Part/Chart.php +++ b/src/PhpWord/Writer/Word2007/Part/Chart.php @@ -282,10 +282,9 @@ class Chart extends AbstractPart $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/148] 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 1eaa6f24..b277494e 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/148] 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 b277494e..4e8195b3 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/148] 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 55b20232..c6b64c28 100644 --- a/src/PhpWord/Writer/AbstractWriter.php +++ b/src/PhpWord/Writer/AbstractWriter.php @@ -360,6 +360,10 @@ abstract class AbstractWriter implements WriterInterface // 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/148] 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 f5cc7ccc..64ddfd86 100644 --- a/src/PhpWord/Element/Image.php +++ b/src/PhpWord/Element/Image.php @@ -335,6 +335,10 @@ class Image extends AbstractElement // 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/148] 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 24f50667..4b411cdc 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 @@ class Table extends Border 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 8bbad107..b3686f90 100644 --- a/src/PhpWord/Writer/Word2007/Style/Table.php +++ b/src/PhpWord/Writer/Word2007/Style/Table.php @@ -74,6 +74,7 @@ class Table extends AbstractStyle $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 @@ class Table extends AbstractStyle $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 fd7ee764380ad1c99c9075be4963d19d239bec54 Mon Sep 17 00:00:00 2001 From: troosan Date: Fri, 29 Dec 2017 03:01:36 +0100 Subject: [PATCH 009/148] create alias for develop branch --- composer.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/composer.json b/composer.json index 3cc4b131..aa4a2415 100644 --- a/composer.json +++ b/composer.json @@ -74,5 +74,10 @@ "psr-4": { "PhpOffice\\PhpWord\\": "src/PhpWord" } + }, + "extra": { + "branch-alias": { + "dev-develop": "0.15.0-dev" + } } } From d2b9e88047c0533db351bcefc0bedbe703b09411 Mon Sep 17 00:00:00 2001 From: troosan Date: Fri, 29 Dec 2017 14:36:07 +0100 Subject: [PATCH 010/148] add parsing of "align" HTML attribute --- CHANGELOG.md | 7 ++++++ samples/Sample_26_Html.php | 2 +- src/PhpWord/Shared/Html.php | 39 ++++++++++++++++++++----------- tests/PhpWord/Shared/HtmlTest.php | 4 +++- 4 files changed, 36 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 93945189..b5396d8d 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.15.0 (?? ??? 2018) +---------------------- +### Added +- Parsing of "align" HTML attribute - @troosan + +### Fixed + v0.14.0 (29 Dec 2017) ---------------------- This release fixes several bugs and adds some new features. diff --git a/samples/Sample_26_Html.php b/samples/Sample_26_Html.php index ba06b063..b993f834 100644 --- a/samples/Sample_26_Html.php +++ b/samples/Sample_26_Html.php @@ -28,7 +28,7 @@ $html .= '
'; -$html .= ' +$html .= '
diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index d8a10b57..38d326c1 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -85,6 +85,8 @@ class Html case 'style': $styles = self::parseStyle($attribute, $styles); break; + case 'align': + $styles['alignment'] = self::mapAlign($attribute->value); } } } @@ -431,20 +433,7 @@ class Html } break; case 'text-align': - switch ($cValue) { - case 'left': - $styles['alignment'] = Jc::START; - break; - case 'right': - $styles['alignment'] = Jc::END; - break; - case 'center': - $styles['alignment'] = Jc::CENTER; - break; - case 'justify': - $styles['alignment'] = Jc::BOTH; - break; - } + $styles['alignment'] = self::mapAlign($cValue); break; case 'font-size': $styles['size'] = Converter::cssToPoint($cValue); @@ -584,6 +573,28 @@ class Html } } + /** + * Transforms a HTML/CSS alignment into a \PhpOffice\PhpWord\SimpleType\Jc + * + * @param string $cssAlignment + * @return string|null + */ + private static function mapAlign($cssAlignment) + { + switch ($cssAlignment) { + case 'left': + return Jc::START; + case 'right': + return Jc::END; + case 'center': + return Jc::CENTER; + case 'justify': + return Jc::BOTH; + } + + return null; + } + /** * Parse line break * diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index d168c09e..c7d36470 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -187,7 +187,7 @@ class HtmlTest extends \PHPUnit\Framework\TestCase { $phpWord = new \PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); - $html = '
header a
+ $html = '
@@ -205,6 +205,8 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); $this->assertTrue($doc->elementExists('/w:document/w:body/w:tbl')); $this->assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tr/w:tc')); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:tbl/w:tblPr/w:jc')); + $this->assertEquals(Jc::START, $doc->getElementAttribute('/w:document/w:body/w:tbl/w:tblPr/w:jc', 'w:val')); } /** From 1d8e7b8374547fac04c432cda2f54503077829f2 Mon Sep 17 00:00:00 2001 From: troosan Date: Fri, 29 Dec 2017 14:36:56 +0100 Subject: [PATCH 011/148] split composer scripts, add description (only works with composer 1.6) --- composer.json | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index aa4a2415..a79c8e19 100644 --- a/composer.json +++ b/composer.json @@ -35,16 +35,28 @@ } ], "scripts": { + "test": [ + "./vendor/bin/phpunit --color=always" + ], + "test-no-coverage": [ + "./vendor/bin/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", - "./vendor/bin/phpunit --color=always" + "@test" ], "fix": [ "./vendor/bin/php-cs-fixer fix --ansi" ] }, + "scripts-descriptions": { + "test": "Runs all unit tests", + "test-no-coverage": "Runs all unit tests, without code coverage", + "check": "Runs PHP CheckStyle and PHP Mess detector", + "fix": "Fixes issues found by PHP-CS" + }, "require": { "php": "^5.3.3 || ^7.0", "ext-xml": "*", From b20cd4fa9f5db9ee8c028d7ebe34597e9c540340 Mon Sep 17 00:00:00 2001 From: troosan Date: Fri, 29 Dec 2017 14:37:26 +0100 Subject: [PATCH 012/148] output the source code of the sample that was run --- samples/Sample_Header.php | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/samples/Sample_Header.php b/samples/Sample_Header.php index c4996049..36478ad6 100644 --- a/samples/Sample_Header.php +++ b/samples/Sample_Header.php @@ -43,13 +43,19 @@ $pageHeading = IS_INDEX ? '' : "

{$pageHeading}

"; // Populate samples $files = ''; if ($handle = opendir('.')) { - while (false !== ($file = readdir($handle))) { + $sampleFiles = array(); + while (false !== ($sampleFile = readdir($handle))) { + $sampleFiles[] = $sampleFile; + } + sort($sampleFiles); + closedir($handle); + + foreach ($sampleFiles as $file) { if (preg_match('/^Sample_\d+_/', $file)) { $name = str_replace('_', ' ', preg_replace('/(Sample_|\.php)/', '', $file)); $files .= "
  • {$name}
  • "; } } - closedir($handle); } /** @@ -78,6 +84,11 @@ function write($phpWord, $filename, $writers) } $result .= getEndingNotes($writers); + $result .= '
    ';
    +    if (file_exists($filename . '.php')) {
    +        $result .= highlight_file($filename . '.php', true);
    +    }
    +    $result .= '
    '; return $result; } From 46e179d1484b12005a0882e5bf12ee76bb5c6856 Mon Sep 17 00:00:00 2001 From: troosan Date: Fri, 29 Dec 2017 14:42:48 +0100 Subject: [PATCH 013/148] add instructions on how to run the samples in a browser --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ac5f3b95..4e3d1e2d 100644 --- a/README.md +++ b/README.md @@ -161,7 +161,8 @@ $objWriter->save('helloWorld.html'); /* Note: we skip PDF, because "HTML-to-PDF" approach is used to create PDF documents. */ ``` -More examples are provided in the [samples folder](samples/). You can also read the [Developers' Documentation](http://phpword.readthedocs.org/) and the [API Documentation](http://phpoffice.github.io/PHPWord/docs/master/) for more detail. +More examples are provided in the [samples folder](samples/). For an easy access to those samples launch `php -S localhost:8000` in the samples directory then browse to [http://localhost:8000](http://localhost:8000) to view the samples. +You can also read the [Developers' Documentation](http://phpword.readthedocs.org/) and the [API Documentation](http://phpoffice.github.io/PHPWord/docs/master/) for more detail. ## Contributing From 709ea1e14c2765ef2c439a46bafde1e027bd23f1 Mon Sep 17 00:00:00 2001 From: troosan Date: Fri, 29 Dec 2017 14:48:12 +0100 Subject: [PATCH 014/148] update changelog [skip ci] --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5396d8d..1f22bb2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). v0.15.0 (?? ??? 2018) ---------------------- ### Added -- Parsing of "align" HTML attribute - @troosan +- Parsing of "align" HTML attribute - @troosan #1231 ### Fixed From 400a8e65d35010c88076e425aec7af1f9132e331 Mon Sep 17 00:00:00 2001 From: Maxim Date: Fri, 29 Dec 2017 21:19:35 +0200 Subject: [PATCH 015/148] rename 'Object' classes to 'ObjectElement' (php 7.2 compatibility) (#1185) merge develop branch --- .travis.yml | 5 +++++ CHANGELOG.md | 3 ++- src/PhpWord/Element/AbstractContainer.php | 6 ++--- src/PhpWord/Element/AbstractElement.php | 7 ++++-- .../Element/{Object.php => OLEObject.php} | 4 ++-- .../Element/{Object.php => OLEObject.php} | 6 ++--- tests/PhpWord/Element/CellTest.php | 2 +- tests/PhpWord/Element/ObjectTest.php | 22 +++++++++---------- tests/PhpWord/Element/SectionTest.php | 2 +- tests/PhpWord/Writer/Word2007/ElementTest.php | 2 +- 10 files changed, 34 insertions(+), 25 deletions(-) rename src/PhpWord/Element/{Object.php => OLEObject.php} (98%) rename src/PhpWord/Writer/Word2007/Element/{Object.php => OLEObject.php} (95%) diff --git a/.travis.yml b/.travis.yml index d63b7bb2..148877ed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,6 +16,11 @@ matrix: - php: 5.6 env: COVERAGE=1 allow_failures: +<<<<<<< HEAD +======= + - php: 7.0 + - php: 7.1 +>>>>>>> branch 'php72_support_object_classes' of https://github.com/SailorMax/PHPWord - php: 7.2 cache: diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f22bb2e..71b331d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,7 +37,8 @@ This version brings compatibility with PHP 7.0 & 7.1 ### Fixed - Loosen dependency to Zend - Images are not being printed when generating PDF - @hubertinio #1074 #431 -- Fixed some PHP 7 warnings - @likeuntomurphy #927 +- Fixed some PHP 7 warnings - @ likeuntomurphy #927 +- Fixed PHP 7.2 compatibility (renamed `Object` class names to `ObjectElement`) - @SailorMax #1185 - Fixed Word 97 reader - @alsofronie @Benpxpx @mario-rivera #912 #920 #892 - Fixed image loading over https - @troosan #988 - Impossibility to set different even and odd page headers - @troosan #981 diff --git a/src/PhpWord/Element/AbstractContainer.php b/src/PhpWord/Element/AbstractContainer.php index e3022b50..b00424b7 100644 --- a/src/PhpWord/Element/AbstractContainer.php +++ b/src/PhpWord/Element/AbstractContainer.php @@ -37,7 +37,7 @@ namespace PhpOffice\PhpWord\Element; * @method PageBreak addPageBreak() * @method Table addTable(mixed $style = null) * @method Image addImage(string $source, mixed $style = null, bool $isWatermark = false) - * @method \PhpOffice\PhpWord\Element\Object addObject(string $source, mixed $style = null) + * @method \PhpOffice\PhpWord\Element\OLEObject addObject(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) * @method Line addLine(mixed $lineStyle = null) @@ -87,7 +87,7 @@ abstract class AbstractContainer extends AbstractElement ); $functions = array(); foreach ($elements as $element) { - $functions['add' . strtolower($element)] = $element; + $functions['add' . strtolower($element)] = $element == 'Object' ? 'OLEObject' : $element; } // Run valid `add` command @@ -193,7 +193,7 @@ abstract class AbstractContainer extends AbstractElement 'Link' => $generalContainers, 'TextBreak' => $generalContainers, 'Image' => $generalContainers, - 'Object' => $generalContainers, + 'OLEObject' => $generalContainers, 'Field' => $generalContainers, 'Line' => $generalContainers, 'Shape' => $generalContainers, diff --git a/src/PhpWord/Element/AbstractElement.php b/src/PhpWord/Element/AbstractElement.php index a65c50f4..63892b74 100644 --- a/src/PhpWord/Element/AbstractElement.php +++ b/src/PhpWord/Element/AbstractElement.php @@ -358,11 +358,14 @@ abstract class AbstractElement */ private function setMediaRelation() { - if (!$this instanceof Link && !$this instanceof Image && !$this instanceof Object) { + if (!$this instanceof Link && !$this instanceof Image && !$this instanceof OLEObject) { return; } $elementName = substr(get_class($this), strrpos(get_class($this), '\\') + 1); + if ($elementName == 'OLEObject') { + $elementName = 'Object'; + } $mediaPart = $this->getMediaPart(); $source = $this->getSource(); $image = null; @@ -372,7 +375,7 @@ abstract class AbstractElement $rId = Media::addElement($mediaPart, strtolower($elementName), $source, $image); $this->setRelationId($rId); - if ($this instanceof Object) { + if ($this instanceof OLEObject) { $icon = $this->getIcon(); $rId = Media::addElement($mediaPart, 'image', $icon, new Image($icon)); $this->setImageRelationId($rId); diff --git a/src/PhpWord/Element/Object.php b/src/PhpWord/Element/OLEObject.php similarity index 98% rename from src/PhpWord/Element/Object.php rename to src/PhpWord/Element/OLEObject.php index 8fe83224..5da94c3a 100644 --- a/src/PhpWord/Element/Object.php +++ b/src/PhpWord/Element/OLEObject.php @@ -21,9 +21,9 @@ use PhpOffice\PhpWord\Exception\InvalidObjectException; use PhpOffice\PhpWord\Style\Image as ImageStyle; /** - * Object element + * OLEObject element */ -class Object extends AbstractElement +class OLEObject extends AbstractElement { /** * Ole-Object Src diff --git a/src/PhpWord/Writer/Word2007/Element/Object.php b/src/PhpWord/Writer/Word2007/Element/OLEObject.php similarity index 95% rename from src/PhpWord/Writer/Word2007/Element/Object.php rename to src/PhpWord/Writer/Word2007/Element/OLEObject.php index 8231ec0c..50891d97 100644 --- a/src/PhpWord/Writer/Word2007/Element/Object.php +++ b/src/PhpWord/Writer/Word2007/Element/OLEObject.php @@ -20,11 +20,11 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Element; use PhpOffice\PhpWord\Writer\Word2007\Style\Image as ImageStyleWriter; /** - * Object element writer + * OLEObject element writer * * @since 0.10.0 */ -class Object extends AbstractElement +class OLEObject extends AbstractElement { /** * Write object element. @@ -33,7 +33,7 @@ class Object extends AbstractElement { $xmlWriter = $this->getXmlWriter(); $element = $this->getElement(); - if (!$element instanceof \PhpOffice\PhpWord\Element\Object) { + if (!$element instanceof \PhpOffice\PhpWord\Element\OLEObject) { return; } diff --git a/tests/PhpWord/Element/CellTest.php b/tests/PhpWord/Element/CellTest.php index 4e8daa0e..a1132cfa 100644 --- a/tests/PhpWord/Element/CellTest.php +++ b/tests/PhpWord/Element/CellTest.php @@ -181,7 +181,7 @@ class CellTest extends \PHPUnit\Framework\TestCase $element = $oCell->addObject($src); $this->assertCount(1, $oCell->getElements()); - $this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\Object', $element); + $this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\OLEObject', $element); } /** diff --git a/tests/PhpWord/Element/ObjectTest.php b/tests/PhpWord/Element/ObjectTest.php index 71f12974..ba761b70 100644 --- a/tests/PhpWord/Element/ObjectTest.php +++ b/tests/PhpWord/Element/ObjectTest.php @@ -18,9 +18,9 @@ namespace PhpOffice\PhpWord\Element; /** - * Test class for PhpOffice\PhpWord\Element\Object + * Test class for PhpOffice\PhpWord\Element\OLEObject * - * @coversDefaultClass \PhpOffice\PhpWord\Element\Object + * @coversDefaultClass \PhpOffice\PhpWord\Element\OLEObject * @runTestsInSeparateProcesses */ class ObjectTest extends \PHPUnit\Framework\TestCase @@ -31,9 +31,9 @@ class ObjectTest extends \PHPUnit\Framework\TestCase public function testConstructWithSupportedFiles() { $src = __DIR__ . '/../_files/documents/reader.docx'; - $oObject = new Object($src); + $oObject = new OLEObject($src); - $this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\Object', $oObject); + $this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\OLEObject', $oObject); $this->assertInstanceOf('PhpOffice\\PhpWord\\Style\\Image', $oObject->getStyle()); $this->assertEquals($src, $oObject->getSource()); } @@ -44,9 +44,9 @@ class ObjectTest extends \PHPUnit\Framework\TestCase public function testConstructWithSupportedFilesLong() { $src = __DIR__ . '/../_files/documents/sheet.xls'; - $oObject = new Object($src); + $oObject = new OLEObject($src); - $this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\Object', $oObject); + $this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\OLEObject', $oObject); $this->assertInstanceOf('PhpOffice\\PhpWord\\Style\\Image', $oObject->getStyle()); $this->assertEquals($src, $oObject->getSource()); } @@ -59,7 +59,7 @@ class ObjectTest extends \PHPUnit\Framework\TestCase public function testConstructWithNotSupportedFiles() { $src = __DIR__ . '/../_files/xsl/passthrough.xsl'; - $oObject = new Object($src); + $oObject = new OLEObject($src); $oObject->getSource(); } @@ -69,9 +69,9 @@ class ObjectTest extends \PHPUnit\Framework\TestCase public function testConstructWithSupportedFilesAndStyle() { $src = __DIR__ . '/../_files/documents/sheet.xls'; - $oObject = new Object($src, array('width' => '230px')); + $oObject = new OLEObject($src, array('width' => '230px')); - $this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\Object', $oObject); + $this->assertInstanceOf('PhpOffice\\PhpWord\\Element\\OLEObject', $oObject); $this->assertInstanceOf('PhpOffice\\PhpWord\\Style\\Image', $oObject->getStyle()); $this->assertEquals($src, $oObject->getSource()); } @@ -82,7 +82,7 @@ class ObjectTest extends \PHPUnit\Framework\TestCase public function testRelationId() { $src = __DIR__ . '/../_files/documents/sheet.xls'; - $oObject = new Object($src); + $oObject = new OLEObject($src); $iVal = rand(1, 1000); $oObject->setRelationId($iVal); @@ -95,7 +95,7 @@ class ObjectTest extends \PHPUnit\Framework\TestCase public function testImageRelationId() { $src = __DIR__ . '/../_files/documents/sheet.xls'; - $oObject = new Object($src); + $oObject = new OLEObject($src); $iVal = rand(1, 1000); $oObject->setImageRelationId($iVal); diff --git a/tests/PhpWord/Element/SectionTest.php b/tests/PhpWord/Element/SectionTest.php index 8b6c9a43..20f0f0f7 100644 --- a/tests/PhpWord/Element/SectionTest.php +++ b/tests/PhpWord/Element/SectionTest.php @@ -70,7 +70,7 @@ class SectionTest extends \PHPUnit\Framework\TestCase 'PageBreak', 'Table', 'ListItem', - 'Object', + 'OLEObject', 'Image', 'Title', 'TextRun', diff --git a/tests/PhpWord/Writer/Word2007/ElementTest.php b/tests/PhpWord/Writer/Word2007/ElementTest.php index 12f810ce..4f0d50d9 100644 --- a/tests/PhpWord/Writer/Word2007/ElementTest.php +++ b/tests/PhpWord/Writer/Word2007/ElementTest.php @@ -44,7 +44,7 @@ class ElementTest extends \PHPUnit\Framework\TestCase { $elements = array( 'CheckBox', 'Container', 'Footnote', 'Image', 'Link', 'ListItem', 'ListItemRun', - 'Object', 'PreserveText', 'Table', 'Text', 'TextBox', 'TextBreak', 'Title', 'TOC', + 'OLEObject', 'PreserveText', 'Table', 'Text', 'TextBox', 'TextBreak', 'Title', 'TOC', 'Field', 'Line', 'Shape', 'Chart', 'FormField', 'SDT', 'Bookmark', ); foreach ($elements as $element) { From 2d87fd320dffbbdafdf280dda78dcfce34f024c1 Mon Sep 17 00:00:00 2001 From: troosan Date: Fri, 29 Dec 2017 20:27:05 +0100 Subject: [PATCH 016/148] fix merge --- .travis.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 148877ed..d63b7bb2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,11 +16,6 @@ matrix: - php: 5.6 env: COVERAGE=1 allow_failures: -<<<<<<< HEAD -======= - - php: 7.0 - - php: 7.1 ->>>>>>> branch 'php72_support_object_classes' of https://github.com/SailorMax/PHPWord - php: 7.2 cache: From 23693b403c32c13a355adf0e2a32642a480066da Mon Sep 17 00:00:00 2001 From: troosan Date: Fri, 29 Dec 2017 21:47:55 +0100 Subject: [PATCH 017/148] change impl to avoid compilation issue --- src/PhpWord/Writer/PDF/MPDF.php | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/PhpWord/Writer/PDF/MPDF.php b/src/PhpWord/Writer/PDF/MPDF.php index e238057b..b6980a9d 100644 --- a/src/PhpWord/Writer/PDF/MPDF.php +++ b/src/PhpWord/Writer/PDF/MPDF.php @@ -29,6 +29,12 @@ use PhpOffice\PhpWord\Writer\WriterInterface; */ class MPDF extends AbstractRenderer implements WriterInterface { + /** + * Overridden to set the correct includefile, only needed for MPDF 5 + * + * @codeCoverageIgnore + * @param PhpWord $phpWord + */ public function __construct(PhpWord $phpWord) { if (file_exists(Settings::getPdfRendererPath() . '/mpdf.php')) { @@ -52,13 +58,8 @@ class MPDF extends AbstractRenderer implements WriterInterface $orientation = strtoupper('portrait'); // Create PDF - if ($this->includeFile != null) { - // MPDF version 5.* - $pdf = new \mpdf(); - } else { - // MPDF version > 6.* - $pdf = new \Mpdf\Mpdf(); - } + $mPdfClass = $this->getMPdfClassName(); + $pdf = new $mPdfClass(); $pdf->_setPageSize($paperSize, $orientation); $pdf->addPage($orientation); @@ -78,4 +79,21 @@ class MPDF extends AbstractRenderer implements WriterInterface parent::restoreStateAfterSave($fileHandle); } + + /** + * Return classname of MPDF to instantiate + * + * @codeCoverageIgnore + * @return string + */ + private function getMPdfClassName() + { + if ($this->includeFile != null) { + // MPDF version 5.* + return '\mpdf'; + } + + // MPDF version > 6.* + return '\Mpdf\Mpdf'; + } } From d480aab1b000c23f1035b62b8370492fe1d4cce2 Mon Sep 17 00:00:00 2001 From: troosan Date: Fri, 29 Dec 2017 21:29:31 +0100 Subject: [PATCH 018/148] add branch alias for 0.15.0 [skip ci] --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index a79c8e19..2d2743ec 100644 --- a/composer.json +++ b/composer.json @@ -89,7 +89,7 @@ }, "extra": { "branch-alias": { - "dev-develop": "0.15.0-dev" + "dev-master": "0.15.0-dev" } } } From 7d929fee8cc0aae31edbe71c7f6adf8cb3c4b545 Mon Sep 17 00:00:00 2001 From: troosan Date: Fri, 29 Dec 2017 21:33:29 +0100 Subject: [PATCH 019/148] add branch alias for 0.15.0 [skip ci] --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 2d2743ec..614865d8 100644 --- a/composer.json +++ b/composer.json @@ -89,7 +89,7 @@ }, "extra": { "branch-alias": { - "dev-master": "0.15.0-dev" + "dev-master": "0.15-dev" } } } From 4a530d1d97b064b87d9e2a1cc64cab996246569c Mon Sep 17 00:00:00 2001 From: troosan Date: Wed, 3 Jan 2018 17:16:19 +0100 Subject: [PATCH 020/148] Do not show script source when running from CLI --- samples/Sample_Header.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/samples/Sample_Header.php b/samples/Sample_Header.php index 36478ad6..ac51f983 100644 --- a/samples/Sample_Header.php +++ b/samples/Sample_Header.php @@ -84,11 +84,6 @@ function write($phpWord, $filename, $writers) } $result .= getEndingNotes($writers); - $result .= '
    ';
    -    if (file_exists($filename . '.php')) {
    -        $result .= highlight_file($filename . '.php', true);
    -    }
    -    $result .= '
    '; return $result; } @@ -127,6 +122,12 @@ function getEndingNotes($writers) } } $result .= '

    '; + + $result .= '
    ';
    +            if (file_exists($filename . '.php')) {
    +                $result .= highlight_file($filename . '.php', true);
    +            }
    +            $result .= '
    '; } } From 99b04f0353e4c2d398f8b4c4db37df5e5772fc1d Mon Sep 17 00:00:00 2001 From: troosan Date: Fri, 12 Jan 2018 23:42:22 +0100 Subject: [PATCH 021/148] fix reading of docx default style (#1238) --- CHANGELOG.md | 7 +- docs/elements.rst | 7 +- docs/general.rst | 3 +- docs/installing.rst | 1 - src/PhpWord/Reader/Word2007/AbstractPart.php | 68 +++++++++++++++++-- src/PhpWord/Reader/Word2007/Settings.php | 4 +- src/PhpWord/Reader/Word2007/Styles.php | 23 +++++++ src/PhpWord/Style/Paragraph.php | 1 - src/PhpWord/Writer/Word2007/Element/Shape.php | 4 +- src/PhpWord/Writer/Word2007/Part/Styles.php | 21 ++++-- .../Writer/Word2007/Style/Paragraph.php | 2 +- 11 files changed, 115 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71b331d6..62694eea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,9 @@ v0.15.0 (?? ??? 2018) - Parsing of "align" HTML attribute - @troosan #1231 ### Fixed +- fix reading of docx default style - @troosan #1238 + + v0.14.0 (29 Dec 2017) ---------------------- @@ -58,6 +61,8 @@ This version brings compatibility with PHP 7.0 & 7.1 ### Deprecated - PhpWord->getProtection(), get it from the settings instead PhpWord->getSettings()->getDocumentProtection(); + + v0.13.0 (31 July 2016) ------------------- This release brings several improvements in `TemplateProcessor`, automatic output escaping feature for OOXML, ODF, HTML, and RTF (turned off, by default). @@ -77,7 +82,7 @@ Manual installation feature has been dropped since the release. Please, use [Com - Improved error message for the case when `autoload.php` is not found. - @RomanSyroeshko #371 - Renamed the `align` option of `NumberingLevel`, `Frame`, `Table`, and `Paragraph` styles into `alignment`. - @RomanSyroeshko - Improved performance of `TemplateProcessor::setValue()`. - @kazitanvirahsan #614, #617 -- Fixed some HTML tags not rendering any output (p, header & table) - #257, #324 - @twmobius and @garethellis +- Fixed some HTML tags not rendering any output (p, header & table) - #257, #324 - @twmobius and @garethellis ### Deprecated - `getAlign` and `setAlign` methods of `NumberingLevel`, `Frame`, `Table`, and `Paragraph` styles. diff --git a/docs/elements.rst b/docs/elements.rst index c73ffa06..94ff2667 100644 --- a/docs/elements.rst +++ b/docs/elements.rst @@ -160,7 +160,7 @@ Parameters: - ``$text``. Text that appears in the document. - ``$depth``. Depth of list item. - ``$fontStyle``. See :ref:`font-style`. -- ``$listStyle``. List style of the current element TYPE\_NUMBER, +- ``$listStyle``. List style of the current element TYPE\_NUMBER, TYPE\_ALPHANUM, TYPE\_BULLET\_FILLED, etc. See list of constants in PHPWord\\Style\\ListItem. - ``$paragraphStyle``. See :ref:`paragraph-style`. @@ -345,7 +345,7 @@ The footnote numbering can be controlled by setting the FootnoteProperties on th .. code-block:: php $fp = new PhpWord\SimpleType\FootnoteProperties(); - //sets the position of the footnote (pageBottom (default), beneathText, sectEnd, docEnd) + //sets the position of the footnote (pageBottom (default), beneathText, sectEnd, docEnd) $fp->setPos(FootnoteProperties::POSITION_DOC_END); //set the number format to use (decimal (default), upperRoman, upperLetter, ...) $fp->setNumFmt(FootnoteProperties::NUMBER_FORMAT_LOWER_ROMAN); @@ -353,7 +353,6 @@ The footnote numbering can be controlled by setting the FootnoteProperties on th $fp->setNumStart(2); //when to restart counting (continuous (default), eachSect, eachPage) $fp->setNumRestart(FootnoteProperties::RESTART_NUMBER_EACH_PAGE); - //And finaly, set it on the Section $section->setFootnoteProperties($properties); @@ -379,7 +378,7 @@ To be completed Fields ------ -Currently the following fields are supported: +Currently the following fields are supported: - PAGE - NUMPAGES diff --git a/docs/general.rst b/docs/general.rst index ae090f2d..09a23cee 100644 --- a/docs/general.rst +++ b/docs/general.rst @@ -167,7 +167,6 @@ Use mirror margins to set up facing pages for double-sided documents, such as bo $phpWord->getSettings()->setMirrorMargins(true); - Spelling and grammatical checks ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -191,7 +190,7 @@ You can also specify the status of the spell and grammar checks, marking spellin Track Revisions ~~~~~~~~~~~~~~~ -Track changes can be activated using ``setTrackRevisions``, you can furture specify +Track changes can be activated using ``setTrackRevisions``, you can furture specify - Not to use move syntax, instead moved items will be seen as deleted in one place and added in another - Not track formatting revisions diff --git a/docs/installing.rst b/docs/installing.rst index 37e4d379..4f407f54 100644 --- a/docs/installing.rst +++ b/docs/installing.rst @@ -51,7 +51,6 @@ Example: } } - Using samples ------------- diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 6a48fd46..3d853e8f 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -307,7 +307,7 @@ abstract class AbstractPart $styleNode = $xmlReader->getElement('w:pPr', $domNode); $styleDefs = array( - 'styleName' => array(self::READ_VALUE, 'w:pStyle'), + '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'), @@ -349,9 +349,9 @@ abstract class AbstractPart $styleNode = $xmlReader->getElement('w:rPr', $domNode); $styleDefs = array( 'styleName' => array(self::READ_VALUE, 'w:rStyle'), - 'name' => array(self::READ_VALUE, 'w:rFonts', 'w:ascii'), + 'name' => array(self::READ_VALUE, 'w:rFonts', array('w:ascii', 'w:hAnsi', 'w:eastAsia', 'w:cs')), 'hint' => array(self::READ_VALUE, 'w:rFonts', 'w:hint'), - 'size' => array(self::READ_SIZE, 'w:sz'), + 'size' => array(self::READ_SIZE, array('w:sz', 'w:szCs')), 'color' => array(self::READ_VALUE, 'w:color'), 'underline' => array(self::READ_VALUE, 'w:u'), 'bold' => array(self::READ_TRUE, 'w:b'), @@ -364,9 +364,7 @@ abstract class AbstractPart 'subScript' => array(self::READ_EQUAL, 'w:vertAlign', 'w:val', 'subscript'), 'fgColor' => array(self::READ_VALUE, 'w:highlight'), 'rtl' => array(self::READ_TRUE, 'w:rtl'), - 'font-latin' => array(self::READ_VALUE, 'w:font', 'w:val'), - 'font-eastAsia' => array(self::READ_VALUE, 'w:font', 'w:eastAsia'), - 'font-bidi' => array(self::READ_VALUE, 'w:font', 'w:bidi'), + 'lang' => array(self::READ_VALUE, 'w:lang'), ); return $this->readStyleDefs($xmlReader, $styleNode, $styleDefs); @@ -400,6 +398,7 @@ abstract class AbstractPart $ucfSide = ucfirst($side); $styleDefs["border{$ucfSide}Size"] = array(self::READ_VALUE, "w:tblBorders/w:$side", 'w:sz'); $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'); } $style = $this->readStyleDefs($xmlReader, $styleNode, $styleDefs); } @@ -428,6 +427,54 @@ abstract class AbstractPart return $this->readStyleDefs($xmlReader, $domNode, $styleDefs); } + /** + * Returns the first child element found + * + * @param XMLReader $xmlReader + * @param \DOMElement $parentNode + * @param string|array $elements + * @return string|null + */ + private function findPossibleElement(XMLReader $xmlReader, \DOMElement $parentNode = null, $elements) + { + if (is_array($elements)) { + //if element is an array, we take the first element that exists in the XML + foreach ($elements as $possibleElement) { + if ($xmlReader->elementExists($possibleElement, $parentNode)) { + return $possibleElement; + } + } + } else { + return $elements; + } + + return null; + } + + /** + * Returns the first attribute found + * + * @param XMLReader $xmlReader + * @param \DOMElement $node + * @param string|array $attributes + * @return string|null + */ + private function findPossibleAttribute(XMLReader $xmlReader, \DOMElement $node, $attributes) + { + //if attribute is an array, we take the first attribute that exists in the XML + if (is_array($attributes)) { + foreach ($attributes as $possibleAttribute) { + if ($xmlReader->getAttribute($possibleAttribute, $node)) { + return $possibleAttribute; + } + } + } else { + return $attributes; + } + + return null; + } + /** * Read style definition * @@ -442,11 +489,18 @@ abstract class AbstractPart $styles = array(); foreach ($styleDefs as $styleProp => $styleVal) { - @list($method, $element, $attribute, $expected) = $styleVal; + list($method, $element, $attribute, $expected) = array_pad($styleVal, 4, null); + + $element = $this->findPossibleElement($xmlReader, $parentNode, $element); + if ($element === null) { + continue; + } if ($xmlReader->elementExists($element, $parentNode)) { $node = $xmlReader->getElement($element, $parentNode); + $attribute = $this->findPossibleAttribute($xmlReader, $node, $attribute); + // Use w:val as default if no attribute assigned $attribute = ($attribute === null) ? 'w:val' : $attribute; $attributeValue = $xmlReader->getAttribute($attribute, $node); diff --git a/src/PhpWord/Reader/Word2007/Settings.php b/src/PhpWord/Reader/Word2007/Settings.php index ccdbed25..581a546d 100644 --- a/src/PhpWord/Reader/Word2007/Settings.php +++ b/src/PhpWord/Reader/Word2007/Settings.php @@ -80,8 +80,8 @@ class Settings extends AbstractPart $themeFontLang = new Language(); $themeFontLang->setLatin($val); - $themeFontLang->setLatin($eastAsia); - $themeFontLang->setLatin($bidi); + $themeFontLang->setEastAsia($eastAsia); + $themeFontLang->setBidirectional($bidi); $phpWord->getSettings()->setThemeFontLang($themeFontLang); } diff --git a/src/PhpWord/Reader/Word2007/Styles.php b/src/PhpWord/Reader/Word2007/Styles.php index b8e6f22b..c6e64e45 100644 --- a/src/PhpWord/Reader/Word2007/Styles.php +++ b/src/PhpWord/Reader/Word2007/Styles.php @@ -19,6 +19,7 @@ namespace PhpOffice\PhpWord\Reader\Word2007; use PhpOffice\Common\XMLReader; use PhpOffice\PhpWord\PhpWord; +use PhpOffice\PhpWord\Style\Language; /** * Styles reader @@ -37,6 +38,28 @@ class Styles extends AbstractPart $xmlReader = new XMLReader(); $xmlReader->getDomFromZip($this->docFile, $this->xmlFile); + $fontDefaults = $xmlReader->getElement('w:docDefaults/w:rPrDefault'); + if ($fontDefaults !== null) { + $fontDefaultStyle = $this->readFontStyle($xmlReader, $fontDefaults); + if (array_key_exists('name', $fontDefaultStyle)) { + $phpWord->setDefaultFontName($fontDefaultStyle['name']); + } + if (array_key_exists('size', $fontDefaultStyle)) { + $phpWord->setDefaultFontSize($fontDefaultStyle['size']); + } + if (array_key_exists('lang', $fontDefaultStyle)) { + $phpWord->getSettings()->setThemeFontLang(new Language($fontDefaultStyle['lang'])); + } + } + + $paragraphDefaults = $xmlReader->getElement('w:docDefaults/w:pPrDefault'); + if ($paragraphDefaults !== null) { + $paragraphDefaultStyle = $this->readParagraphStyle($xmlReader, $paragraphDefaults); + if ($paragraphDefaultStyle != null) { + $phpWord->setDefaultParagraphStyle(); + } + } + $nodes = $xmlReader->getElements('w:style'); if ($nodes->length > 0) { foreach ($nodes as $node) { diff --git a/src/PhpWord/Style/Paragraph.php b/src/PhpWord/Style/Paragraph.php index c00dc97c..7e40d9e4 100644 --- a/src/PhpWord/Style/Paragraph.php +++ b/src/PhpWord/Style/Paragraph.php @@ -20,7 +20,6 @@ namespace PhpOffice\PhpWord\Style; use PhpOffice\Common\Text; use PhpOffice\PhpWord\Exception\InvalidStyleException; use PhpOffice\PhpWord\SimpleType\Jc; -use PhpOffice\PhpWord\SimpleType\LineSpacingRule; use PhpOffice\PhpWord\SimpleType\TextAlignment; /** diff --git a/src/PhpWord/Writer/Word2007/Element/Shape.php b/src/PhpWord/Writer/Word2007/Element/Shape.php index e384db06..9f111293 100644 --- a/src/PhpWord/Writer/Word2007/Element/Shape.php +++ b/src/PhpWord/Writer/Word2007/Element/Shape.php @@ -154,12 +154,12 @@ class Shape extends AbstractElement case 'arc': case 'line': $points = explode(' ', $value); - @list($start, $end) = $points; + list($start, $end) = array_pad($points, 2, null); $points = array('start' => $start, 'end' => $end); break; case 'curve': $points = explode(' ', $value); - @list($start, $end, $point1, $point2) = $points; + list($start, $end, $point1, $point2) = array_pad($points, 4, null); $points = array('start' => $start, 'end' => $end, 'point1' => $point1, 'point2' => $point2); break; } diff --git a/src/PhpWord/Writer/Word2007/Part/Styles.php b/src/PhpWord/Writer/Word2007/Part/Styles.php index 126cda4f..1cc94806 100644 --- a/src/PhpWord/Writer/Word2007/Part/Styles.php +++ b/src/PhpWord/Writer/Word2007/Part/Styles.php @@ -18,7 +18,6 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Part; use PhpOffice\Common\XMLWriter; -use PhpOffice\PhpWord\Settings as PhpWordSettings; use PhpOffice\PhpWord\Style; use PhpOffice\PhpWord\Style\Font as FontStyle; use PhpOffice\PhpWord\Style\Paragraph as ParagraphStyle; @@ -82,9 +81,10 @@ class Styles extends AbstractPart */ private function writeDefaultStyles(XMLWriter $xmlWriter, $styles) { - $fontName = PhpWordSettings::getDefaultFontName(); - $fontSize = PhpWordSettings::getDefaultFontSize(); - $language = $this->getParentWriter()->getPhpWord()->getSettings()->getThemeFontLang(); + $phpWord = $this->getParentWriter()->getPhpWord(); + $fontName = $phpWord->getDefaultFontName(); + $fontSize = $phpWord->getDefaultFontSize(); + $language = $phpWord->getSettings()->getThemeFontLang(); $latinLanguage = ($language == null || $language->getLatin() === null) ? 'en-US' : $language->getLatin(); // Default font @@ -123,7 +123,18 @@ class Styles extends AbstractPart $xmlWriter->writeAttribute('w:val', 'Normal'); $xmlWriter->endElement(); // w:name if (isset($styles['Normal'])) { - $styleWriter = new ParagraphStyleWriter($xmlWriter, $styles['Normal']); + $normalStyle = $styles['Normal']; + // w:pPr + if ($normalStyle instanceof Fontstyle && $normalStyle->getParagraph() != null) { + $styleWriter = new ParagraphStyleWriter($xmlWriter, $normalStyle->getParagraph()); + $styleWriter->write(); + } elseif ($normalStyle instanceof ParagraphStyle) { + $styleWriter = new ParagraphStyleWriter($xmlWriter, $normalStyle); + $styleWriter->write(); + } + + // w:rPr + $styleWriter = new FontStyleWriter($xmlWriter, $normalStyle); $styleWriter->write(); } $xmlWriter->endElement(); // w:style diff --git a/src/PhpWord/Writer/Word2007/Style/Paragraph.php b/src/PhpWord/Writer/Word2007/Style/Paragraph.php index 424b87f8..8915fb4c 100644 --- a/src/PhpWord/Writer/Word2007/Style/Paragraph.php +++ b/src/PhpWord/Writer/Word2007/Style/Paragraph.php @@ -109,7 +109,7 @@ class Paragraph extends AbstractStyle //Paragraph contextualSpacing $xmlWriter->writeElementIf($styles['contextualSpacing'] === true, 'w:contextualSpacing'); - //Paragraph contextualSpacing + //Paragraph textAlignment $xmlWriter->writeElementIf($styles['textAlignment'] !== null, 'w:textAlignment', 'w:val', $styles['textAlignment']); // Child style: alignment, indentation, spacing, and shading From 4c68ebbe9dcb887c049ff1569df170551c2d5d0e Mon Sep 17 00:00:00 2001 From: samimussbach Date: Sat, 13 Jan 2018 10:03:53 +0100 Subject: [PATCH 022/148] Parse formatting inside HTML lists (#1239) --- CHANGELOG.md | 1 + README.md | 2 +- docs/elements.rst | 4 +- samples/Sample_26_Html.php | 39 +++++++++--- src/PhpWord/Element/AbstractContainer.php | 7 ++- src/PhpWord/Shared/Html.php | 75 ++++++++++++++++------ tests/PhpWord/Shared/HtmlTest.php | 76 +++++++++++++++++++++-- 7 files changed, 170 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62694eea..d6f8b2da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ v0.15.0 (?? ??? 2018) ---------------------- ### Added - Parsing of "align" HTML attribute - @troosan #1231 +- Parse formatting inside HTML lists - @troosan @samimussbach #1239 #945 #1215 #508 ### Fixed - fix reading of docx default style - @troosan #1238 diff --git a/README.md b/README.md index 07b0d439..59fc3c44 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ PHPWord is a library written in pure PHP that provides a set of classes to write to and read from different document file formats. The current version of PHPWord supports Microsoft [Office Open XML](http://en.wikipedia.org/wiki/Office_Open_XML) (OOXML or OpenXML), OASIS [Open Document Format for Office Applications](http://en.wikipedia.org/wiki/OpenDocument) (OpenDocument or ODF), [Rich Text Format](http://en.wikipedia.org/wiki/Rich_Text_Format) (RTF), HTML, and PDF. -PHPWord is an open source project licensed under the terms of [LGPL version 3](https://github.com/PHPOffice/PHPWord/blob/develop/COPYING.LESSER). PHPWord is aimed to be a high quality software product by incorporating [continuous integration](https://travis-ci.org/PHPOffice/PHPWord) and [unit testing](http://phpoffice.github.io/PHPWord/coverage/develop/). You can learn more about PHPWord by reading the [Developers' Documentation](http://phpword.readthedocs.org/) and the [API Documentation](http://phpoffice.github.io/PHPWord/docs/develop/). +PHPWord is an open source project licensed under the terms of [LGPL version 3](https://github.com/PHPOffice/PHPWord/blob/develop/COPYING.LESSER). PHPWord is aimed to be a high quality software product by incorporating [continuous integration](https://travis-ci.org/PHPOffice/PHPWord) and [unit testing](http://phpoffice.github.io/PHPWord/coverage/develop/). You can learn more about PHPWord by reading the [Developers' Documentation](http://phpword.readthedocs.org/). If you have any questions, please ask on [StackOverFlow](https://stackoverflow.com/questions/tagged/phpword) diff --git a/docs/elements.rst b/docs/elements.rst index 94ff2667..fe673304 100644 --- a/docs/elements.rst +++ b/docs/elements.rst @@ -405,8 +405,10 @@ For instance for the INDEX field, you can do the following (See `Index Field for $fieldText->addText('My '); $fieldText->addText('bold index', ['bold' => true]); $fieldText->addText(' entry'); + $section->addField('XE', array(), array(), $fieldText); - $section->addField('INDEX', array(), array('\\e " " \\h "A" \\c "3"'), $fieldText); + //this actually adds the index + $section->addField('INDEX', array(), array('\\e " " \\h "A" \\c "3"'), 'right click to update index'); Line ---- diff --git a/samples/Sample_26_Html.php b/samples/Sample_26_Html.php index b993f834..99a35f9c 100644 --- a/samples/Sample_26_Html.php +++ b/samples/Sample_26_Html.php @@ -9,25 +9,50 @@ $section = $phpWord->addSection(); $html = '

    Adding element via HTML

    '; $html .= '

    Some well formed HTML snippet needs to be used

    '; $html .= '

    With for example some1 inline formatting1

    '; -$html .= '

    Unordered (bulleted) list:

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

    Ordered (numbered) list:

    '; -$html .= '
    1. Item 1
    2. Item 2
    '; -$html .= '

    List with complex content:

    '; +$html .= '

    Unordered (bulleted) list:

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

    Ordered (numbered) list:

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

    2. +
    3. List 1 item 2
    4. +
        +
      1. sub list 1
      2. +
      3. sub list 2
      4. +
      +
    5. List 1 item 3
    6. +
    +

    A second list, numbering should restart

    +
      +
    1. List 2 item 1
    2. +
    3. List 2 item 2
    4. +
        +
      1. sub list 1
      2. +
      3. sub list 2
      4. +
      +
    5. List 2 item 3
    6. +
        +
      1. sub list 1, restarts with a
      2. +
      3. sub list 2
      4. +
      +
    '; + +$html .= '

    List with formatted content:

    '; $html .= '
    • - list item1 + big list item1
    • - list item2 + list item2 in bold
    '; +$html .= '

    A table with formatting:

    '; $html .= '
    header a
    diff --git a/src/PhpWord/Element/AbstractContainer.php b/src/PhpWord/Element/AbstractContainer.php index b00424b7..28d45672 100644 --- a/src/PhpWord/Element/AbstractContainer.php +++ b/src/PhpWord/Element/AbstractContainer.php @@ -33,11 +33,10 @@ namespace PhpOffice\PhpWord\Element; * @method CheckBox addCheckBox(string $name, $text, mixed $fStyle = null, mixed $pStyle = null) * @method Title addTitle(string $text, int $depth = 1) * @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 \PhpOffice\PhpWord\Element\OLEObject addObject(string $source, mixed $style = 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) * @method Line addLine(mixed $lineStyle = null) @@ -46,6 +45,8 @@ namespace PhpOffice\PhpWord\Element; * @method FormField addFormField(string $type, mixed $fStyle = null, mixed $pStyle = null) * @method SDT addSDT(string $type) * + * @method \PhpOffice\PhpWord\Element\OLEObject addObject(string $source, mixed $style = null) deprecated, use addOLEObject instead + * * @since 0.10.0 */ abstract class AbstractContainer extends AbstractElement @@ -200,7 +201,7 @@ abstract class AbstractContainer extends AbstractElement 'FormField' => $generalContainers, 'SDT' => $generalContainers, 'TrackChange' => $generalContainers, - 'TextRun' => array('Section', 'Header', 'Footer', 'Cell', 'TextBox', 'TrackChange'), + 'TextRun' => array('Section', 'Header', 'Footer', 'Cell', 'TextBox', 'TrackChange', 'ListItemRun'), 'ListItem' => array('Section', 'Header', 'Footer', 'Cell', 'TextBox'), 'ListItemRun' => array('Section', 'Header', 'Footer', 'Cell', 'TextBox'), 'Table' => array('Section', 'Header', 'Footer', 'Cell', 'TextBox'), diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 38d326c1..fd0bd545 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -18,10 +18,10 @@ namespace PhpOffice\PhpWord\Shared; use PhpOffice\PhpWord\Element\AbstractContainer; -use PhpOffice\PhpWord\Element\Cell; use PhpOffice\PhpWord\Element\Row; use PhpOffice\PhpWord\Element\Table; use PhpOffice\PhpWord\SimpleType\Jc; +use PhpOffice\PhpWord\SimpleType\NumberFormat; /** * Common Html functions @@ -30,6 +30,8 @@ use PhpOffice\PhpWord\SimpleType\Jc; */ class Html { + private static $listIndex = 0; + /** * Add HTML parts. * @@ -135,8 +137,8 @@ class Html 'tr' => array('Row', $node, $element, $styles, null, null, null), 'td' => array('Cell', $node, $element, $styles, null, null, null), 'th' => array('Cell', $node, $element, $styles, null, null, null), - 'ul' => array('List', null, null, $styles, $data, 3, null), - 'ol' => array('List', null, null, $styles, $data, 7, null), + 'ul' => array('List', $node, $element, $styles, $data, null, null), + 'ol' => array('List', $node, $element, $styles, $data, null, null), 'li' => array('ListItem', $node, $element, $styles, $data, null, null), 'img' => array('Image', $node, $element, $styles, null, null, null), 'br' => array('LineBreak', null, $element, $styles, null, null, null), @@ -330,7 +332,7 @@ class Html * @param \DOMNode $node * @param \PhpOffice\PhpWord\Element\Table $element * @param array &$styles - * @return Cell $element + * @return \PhpOffice\PhpWord\Element\Cell $element */ private static function parseCell($node, $element, &$styles) { @@ -365,18 +367,56 @@ class Html /** * Parse list node * + * @param \DOMNode $node + * @param \PhpOffice\PhpWord\Element\AbstractContainer $element * @param array &$styles * @param array &$data - * @param string $argument1 List type */ - private static function parseList(&$styles, &$data, $argument1) + private static function parseList($node, $element, &$styles, &$data) { + $isOrderedList = $node->nodeName == 'ol'; if (isset($data['listdepth'])) { $data['listdepth']++; } else { $data['listdepth'] = 0; + $styles['list'] = 'listStyle_' . self::$listIndex++; + $element->getPhpWord()->addNumberingStyle($styles['list'], self::getListStyle($isOrderedList)); } - $styles['list']['listType'] = $argument1; + } + + private static function getListStyle($isOrderedList) + { + if ($isOrderedList) { + return array( + 'type' => 'multilevel', + 'levels' => array( + array('format' => NumberFormat::DECIMAL, 'text' => '%1.', 'alignment' => 'left', 'tabPos' => 720, 'left' => 720, 'hanging' => 360), + array('format' => NumberFormat::LOWER_LETTER, 'text' => '%2.', 'alignment' => 'left', 'tabPos' => 1440, 'left' => 1440, 'hanging' => 360), + array('format' => NumberFormat::LOWER_ROMAN, 'text' => '%3.', 'alignment' => 'right', 'tabPos' => 2160, 'left' => 2160, 'hanging' => 180), + array('format' => NumberFormat::DECIMAL, 'text' => '%4.', 'alignment' => 'left', 'tabPos' => 2880, 'left' => 2880, 'hanging' => 360), + array('format' => NumberFormat::LOWER_LETTER, 'text' => '%5.', 'alignment' => 'left', 'tabPos' => 3600, 'left' => 3600, 'hanging' => 360), + array('format' => NumberFormat::LOWER_ROMAN, 'text' => '%6.', 'alignment' => 'right', 'tabPos' => 4320, 'left' => 4320, 'hanging' => 180), + array('format' => NumberFormat::DECIMAL, 'text' => '%7.', 'alignment' => 'left', 'tabPos' => 5040, 'left' => 5040, 'hanging' => 360), + array('format' => NumberFormat::LOWER_LETTER, 'text' => '%8.', 'alignment' => 'left', 'tabPos' => 5760, 'left' => 5760, 'hanging' => 360), + array('format' => NumberFormat::LOWER_ROMAN, 'text' => '%9.', 'alignment' => 'right', 'tabPos' => 6480, 'left' => 6480, 'hanging' => 180), + ), + ); + } + + return array( + 'type' => 'hybridMultilevel', + 'levels' => array( + array('format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 720, 'left' => 720, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'), + array('format' => NumberFormat::BULLET, 'text' => 'o', 'alignment' => 'left', 'tabPos' => 1440, 'left' => 1440, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'), + array('format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 2160, 'left' => 2160, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'), + array('format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 2880, 'left' => 2880, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'), + array('format' => NumberFormat::BULLET, 'text' => 'o', 'alignment' => 'left', 'tabPos' => 3600, 'left' => 3600, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'), + array('format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 4320, 'left' => 4320, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'), + array('format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 5040, 'left' => 5040, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'), + array('format' => NumberFormat::BULLET, 'text' => 'o', 'alignment' => 'left', 'tabPos' => 5760, 'left' => 5760, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'), + array('format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 6480, 'left' => 6480, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'), + ), + ); } /** @@ -394,17 +434,10 @@ class Html { $cNodes = $node->childNodes; if (!empty($cNodes)) { - $text = ''; + $listRun = $element->addListItemRun($data['listdepth'], $styles['list'], $styles['paragraph']); foreach ($cNodes as $cNode) { - if ($cNode->nodeName == '#text') { - $text = $cNode->nodeValue; - } + self::parseNode($cNode, $listRun, $styles, $data); } - //ideally we should be parsing child nodes for any style, for now just take the text - if ('' == trim($text) && '' != trim($node->textContent)) { - $text = trim($node->textContent); - } - $element->addListItem($text, $data['listdepth'], $styles['font'], $styles['list'], $styles['paragraph']); } } @@ -462,6 +495,12 @@ class Html } $styles['italic'] = $tValue; break; + case 'margin-top': + $styles['spaceBefore'] = Converter::cssToPoint($cValue); + break; + case 'margin-bottom': + $styles['spaceAfter'] = Converter::cssToPoint($cValue); + break; case 'border-color': $styles['color'] = trim($cValue, '#'); break; @@ -582,14 +621,14 @@ class Html private static function mapAlign($cssAlignment) { switch ($cssAlignment) { - case 'left': - return Jc::START; case 'right': return Jc::END; case 'center': return Jc::CENTER; case 'justify': return Jc::BOTH; + default: + return Jc::START; } return null; diff --git a/tests/PhpWord/Shared/HtmlTest.php b/tests/PhpWord/Shared/HtmlTest.php index c7d36470..9c4cfd55 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -35,7 +35,8 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $content = ''; // Default - $section = new Section(1); + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); $this->assertCount(0, $section->getElements()); // Heading @@ -57,7 +58,7 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $this->assertCount(7, $section->getElements()); // Other parts - $section = new Section(1); + $section = $phpWord->addSection(); $content = ''; $content .= '
    HeaderContent
    '; $content .= '
    • Bullet
      • Bullet
    '; @@ -172,10 +173,11 @@ class HtmlTest extends \PHPUnit\Framework\TestCase { $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:jc')); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:pPr/w:spacing')); $this->assertEquals(Jc::CENTER, $doc->getElementAttribute('/w:document/w:body/w:p[1]/w:pPr/w:jc', 'w:val')); $this->assertEquals('single', $doc->getElementAttribute('/w:document/w:body/w:p[1]/w:r/w:rPr/w:u', 'w:val')); } @@ -224,7 +226,7 @@ class HtmlTest extends \PHPUnit\Framework\TestCase
  • - list item2 + list item2
  • '; @@ -235,6 +237,69 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:t')); $this->assertEquals('list item1', $doc->getElement('/w:document/w:body/w:p[1]/w:r/w:t')->nodeValue); $this->assertEquals('list item2', $doc->getElement('/w:document/w:body/w:p[2]/w:r/w:t')->nodeValue); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p/w:r/w:rPr/w:b')); + } + + /** + * Tests parsing of ul/li + */ + public function tesOrderedListNumbering() + { + $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. List 2 item 2
    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 + */ + public function testParseListWithFormat() + { + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + $html = preg_replace('/\s+/', ' ', '
      +
    • Some text before + + list item1 bold with text after bold + + and some after +
    • +
    • + + list item2 + +
    • +
    '); + Html::addHtml($section, $html, false, false); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + $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 item2', $doc->getElement('/w:document/w:body/w:p[2]/w:r/w:t')->nodeValue); + $this->assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:r[3]/w:rPr/w:b')); + $this->assertEquals('bold', $doc->getElement('/w:document/w:body/w:p[1]/w:r[3]/w:t')->nodeValue); } /** @@ -255,6 +320,9 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $this->assertEquals('with a linebreak.', $doc->getElement('/w:document/w:body/w:p/w:r[2]/w:t')->nodeValue); } + /** + * Test parsing of img + */ public function testParseImage() { $src = __DIR__ . '/../_files/images/firefox.png'; From 8ed3cacfe8d6ddb9c44843ed981d0bede3a9aab9 Mon Sep 17 00:00:00 2001 From: Gabriel Caruso Date: Tue, 16 Jan 2018 20:19:54 -0200 Subject: [PATCH 023/148] 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 47dae29b..b6d1145c 100644 --- a/src/PhpWord/Writer/Word2007/Element/Container.php +++ b/src/PhpWord/Writer/Word2007/Element/Container.php @@ -46,7 +46,7 @@ class Container extends AbstractElement 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 0425a25cdbbb820eded9473f4026ef32db57baa4 Mon Sep 17 00:00:00 2001 From: troosan Date: Thu, 25 Jan 2018 23:24:21 +0100 Subject: [PATCH 024/148] Add parsing of HTML links --- samples/Sample_26_Html.php | 2 ++ src/PhpWord/Shared/Html.php | 23 +++++++++++++++++++++++ tests/PhpWord/Shared/HtmlTest.php | 13 +++++++++++++ 3 files changed, 38 insertions(+) diff --git a/samples/Sample_26_Html.php b/samples/Sample_26_Html.php index 99a35f9c..69d9d131 100644 --- a/samples/Sample_26_Html.php +++ b/samples/Sample_26_Html.php @@ -10,6 +10,8 @@ $html = '

    Adding element via HTML

    '; $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 .= '

    Unordered (bulleted) list:

    '; $html .= '
    • Item 1
    • Item 2
      • Item 2.1
      • Item 2.1
    '; diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index fd0bd545..0f5f446a 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -142,6 +142,7 @@ class Html 'li' => array('ListItem', $node, $element, $styles, $data, null, null), 'img' => array('Image', $node, $element, $styles, null, null, null), 'br' => array('LineBreak', null, $element, $styles, null, null, null), + 'a' => array('Link', $node, $element, $styles, null, null, null), ); $newElement = null; @@ -643,4 +644,26 @@ class Html { $element->addTextBreak(); } + + /** + * Parse link node + * + * @param \DOMNode $node + * @param \PhpOffice\PhpWord\Element\AbstractContainer $element + * @param array $styles + */ + private static function parseLink($node, $element, &$styles) + { + $target = null; + foreach ($node->attributes as $attribute) { + switch ($attribute->name) { + case 'href': + $target = $attribute->value; + break; + } + } + self::parseInlineStyle($node, $styles['font']); + + 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 9c4cfd55..6122924f 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -341,4 +341,17 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $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')); } + + public function testParseLink() + { + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $section = $phpWord->addSection(); + $html = '

    link text

    '; + Html::addHtml($section, $html); + + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + + $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); + } } From 30183e28810391b66c07e8f896421449830a3558 Mon Sep 17 00:00:00 2001 From: Nicolas Dermine Date: Fri, 26 Jan 2018 18:31:35 +0100 Subject: [PATCH 025/148] fix typo in comment --- src/PhpWord/TemplateProcessor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpWord/TemplateProcessor.php b/src/PhpWord/TemplateProcessor.php index c46038ee..5dd7b0bf 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -422,7 +422,7 @@ class TemplateProcessor } /* - * Note: we do not use `rename` function here, because it looses file ownership data on Windows platform. + * Note: we do not use `rename` function here, because it loses file ownership data on Windows platform. * As a result, user cannot open the file directly getting "Access denied" message. * * @see https://github.com/PHPOffice/PHPWord/issues/532 From caba7e238ff05c2cfd2a438d3f4cb77ee235623e Mon Sep 17 00:00:00 2001 From: Samuel Laulhau Date: Wed, 31 Jan 2018 10:17:40 +0100 Subject: [PATCH 026/148] 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 51de3305..00000000 --- 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 027/148] 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 69d9d131..b05f8d08 100644 --- a/samples/Sample_26_Html.php +++ b/samples/Sample_26_Html.php @@ -29,10 +29,13 @@ $html .= '
      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 6122924f..936c35f9 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -272,6 +272,43 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $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 028/148] 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 6122924f..97a8fb15 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -243,7 +243,7 @@ class HtmlTest extends \PHPUnit\Framework\TestCase /** * Tests parsing of ul/li */ - public function tesOrderedListNumbering() + public function testOrderedListNumbering() { $phpWord = new \PhpOffice\PhpWord\PhpWord(); $section = $phpWord->addSection(); From edd9617c03888ce4dd2e28c2fcacfad98194f4fc Mon Sep 17 00:00:00 2001 From: Nicolas Dermine Date: Sun, 4 Feb 2018 08:42:38 +0100 Subject: [PATCH 029/148] fix typo --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 335ad2d5..e62f2e6f 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 030/148] 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 d6f8b2da..fca2922c 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 69d9d131..d54d548c 100644 --- a/samples/Sample_26_Html.php +++ b/samples/Sample_26_Html.php @@ -7,11 +7,13 @@ $phpWord = new \PhpOffice\PhpWord\PhpWord(); $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 @@ $html .= ' - +
          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 0f5f446a..2eeaae8b 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -31,6 +31,7 @@ use PhpOffice\PhpWord\SimpleType\NumberFormat; class Html { private static $listIndex = 0; + private static $xpath; /** * Add HTML parts. @@ -65,6 +66,7 @@ class Html $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 @@ class Html break; case 'align': $styles['alignment'] = self::mapAlign($attribute->value); + break; + case 'lang': + $styles['lang'] = $attribute->value; + break; } } } @@ -343,8 +349,33 @@ class Html if (!empty($colspan)) { $cellStyles['gridSpan'] = $colspan - 0; } + $cell = $element->addCell(null, $cellStyles); - return $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 true; } /** @@ -469,6 +500,9 @@ class Html 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 @@ class Html 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 9c2714dc..ecaad416 100644 --- a/src/PhpWord/Writer/Word2007/Style/Font.php +++ b/src/PhpWord/Writer/Word2007/Style/Font.php @@ -90,6 +90,10 @@ class Font extends AbstractStyle $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 97a8fb15..7d5f0b4c 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -259,7 +259,7 @@ class HtmlTest extends \PHPUnit\Framework\TestCase 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 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $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 031/148] 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 2eeaae8b..e11d7390 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -366,10 +366,6 @@ class Html */ 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 7d5f0b4c..44fe97fc 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -150,6 +150,33 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $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 @@ class HtmlTest extends \PHPUnit\Framework\TestCase 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 032/148] 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 e11d7390..2a92ed2a 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -339,7 +339,7 @@ class Html * @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 033/148] 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 2a92ed2a..a3ea0cc0 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -366,7 +366,7 @@ class Html */ 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 034/148] 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 63892b74..52279645 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 @@ abstract class AbstractElement $this->commentRangeEnd->setEndElement($this); } + public function getParent() + { + return $this->parent; + } + /** * Set parent container * @@ -331,6 +343,7 @@ abstract class AbstractElement 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 a3ea0cc0..971776ff 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -366,7 +366,7 @@ class Html */ 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 @@ class Html */ 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 @@ class Html $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 035/148] 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 fca2922c..21f4ec81 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 b1ebf349..ac68b887 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -323,7 +323,7 @@ class HtmlTest extends \PHPUnit\Framework\TestCase 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 036/148] 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 21f4ec81..3d3f60f3 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 6e505fdb..f6086357 100644 --- a/samples/Sample_26_Html.php +++ b/samples/Sample_26_Html.php @@ -37,7 +37,6 @@ $html .= '
          1. sub list 2
          -
        3. 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 037/148] 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 | 60 +++++++++++----- 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, 488 insertions(+), 40 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 d6f8b2da..f82759dc 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 fe673304..7df3b163 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 8b05b9e8..c4db7f61 100644 --- a/samples/Sample_16_Object.php +++ b/samples/Sample_16_Object.php @@ -9,7 +9,7 @@ $phpWord = new \PhpOffice\PhpWord\PhpWord(); $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 00000000..e6a30668 --- /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 18836929..205ff598 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 44327f26..dde616cc 100644 --- a/src/PhpWord/Element/TrackChange.php +++ b/src/PhpWord/Element/TrackChange.php @@ -20,14 +20,25 @@ namespace PhpOffice\PhpWord\Element; /** * 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 @@ class TrackChange extends AbstractContainer { 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 8843d8a2..7a7a0468 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 @@ class Content extends AbstractPart $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 @@ class Content extends AbstractPart $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 @@ class Content extends AbstractPart $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 3d853e8f..366bde7e 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 @@ abstract class AbstractPart } 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 @@ abstract class AbstractPart */ 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 @@ abstract class AbstractPart } } 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 c6e64e45..8719641e 100644 --- a/src/PhpWord/Reader/Word2007/Styles.php +++ b/src/PhpWord/Reader/Word2007/Styles.php @@ -56,7 +56,7 @@ class Styles extends AbstractPart 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 71cb7566..9f8f7773 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 @@ class Text extends AbstractElement $content .= ""; } + //open track change tag + $content .= $this->writeTrackChangeOpening(); + return $content; } @@ -132,6 +136,10 @@ class Text extends AbstractElement 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 @@ class Text extends AbstractElement 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 1fc0b800..f9259fc5 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 @@ class Text extends AbstractElement 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()); - } 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->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($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(); + } } 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 8ae4dca9..19d3e54a 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 @@ class Content extends AbstractPart $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 @@ class Content extends AbstractPart $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 e7149432..130b912b 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 @@ class Text extends AbstractElement $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 00000000..3249f10b --- /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 97a8fb15..1ad2ff53 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -259,7 +259,7 @@ class HtmlTest extends \PHPUnit\Framework\TestCase 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 4f0d50d9..f91a8479 100644 --- a/tests/PhpWord/Writer/Word2007/ElementTest.php +++ b/tests/PhpWord/Writer/Word2007/ElementTest.php @@ -19,8 +19,8 @@ namespace PhpOffice\PhpWord\Writer\Word2007; 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 @@ class ElementTest extends \PHPUnit\Framework\TestCase $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 038/148] 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 3d853e8f..5ce84650 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -93,7 +93,7 @@ abstract class AbstractPart * * @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 @@ abstract class AbstractPart * * @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 @@ abstract class AbstractPart $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 00000000..67c2eb13 --- /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 00000000..f138ac76 --- /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 039/148] update changelog --- CHANGELOG.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d3f60f3..ae661e5b 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 040/148] 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 ae661e5b..3b0110b9 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 00000000..649cc7b8 --- /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 bdea985a..f29880d4 100644 --- a/src/PhpWord/Writer/HTML/Element/Link.php +++ b/src/PhpWord/Writer/HTML/Element/Link.php @@ -37,12 +37,12 @@ class Link extends Text 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 86856d5c..fc092ba3 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 bdfc44e3..f2bc7175 100644 --- a/tests/PhpWord/Writer/HTMLTest.php +++ b/tests/PhpWord/Writer/HTMLTest.php @@ -73,6 +73,7 @@ class HTMLTest extends \PHPUnit\Framework\TestCase ); $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 @@ class HTMLTest extends \PHPUnit\Framework\TestCase $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 041/148] 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 cff513a3..24ba001c 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 042/148] 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 7eff87bc..5e73d4e4 100644 --- a/src/PhpWord/Element/Image.php +++ b/src/PhpWord/Element/Image.php @@ -313,7 +313,7 @@ class Image extends AbstractElement $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 @@ class Image extends AbstractElement $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 043/148] 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 a3d454f3..aa397949 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 @@ class Table extends Border 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 620e4fbf..2c4066f1 100644 --- a/src/PhpWord/Writer/Word2007/Style/Table.php +++ b/src/PhpWord/Writer/Word2007/Style/Table.php @@ -77,6 +77,7 @@ class Table extends AbstractStyle } $this->writeWidth($xmlWriter, $style->getWidth(), $style->getUnit()); + $this->writeLayout($xmlWriter, $style->getStretch()); $this->writeMargin($xmlWriter, $style); $this->writeBorder($xmlWriter, $style); @@ -106,6 +107,20 @@ class Table extends AbstractStyle $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 044/148] 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 344517c7..762bf560 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 6166f5c9..031f3759 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 9276823b..09d32dbb 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -425,6 +425,7 @@ abstract class AbstractPart $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 aa397949..d0ff47ed 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 @@ class Table extends Border } /** - * 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 26df8436..e2e8f978 100644 --- a/src/PhpWord/Writer/Word2007/Style/Table.php +++ b/src/PhpWord/Writer/Word2007/Style/Table.php @@ -77,7 +77,7 @@ class Table extends AbstractStyle } $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 @@ class Table extends AbstractStyle * * @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 0966ea4d..8bebce91 100644 --- a/tests/PhpWord/Element/ImageTest.php +++ b/tests/PhpWord/Element/ImageTest.php @@ -210,6 +210,27 @@ class ImageTest extends \PHPUnit\Framework\TestCase $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 00000000..ce59f4c3 --- /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 2d57b1b8..dafdeb31 100644 --- a/tests/PhpWord/Style/TableTest.php +++ b/tests/PhpWord/Style/TableTest.php @@ -172,4 +172,15 @@ class TableTest extends \PHPUnit\Framework\TestCase $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 00000000..a89dd610 --- /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 045/148] 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 7df3b163..12d46908 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 09a23cee..99d8b3ba 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 031f3759..8f462a8c 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 046/148] 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 3569cc50..dc194d59 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 12d46908..d13abc56 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 8f462a8c..9d1cc4c5 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 047/148] 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 9d1cc4c5..8e155ca2 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 048/148] 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 614865d8..bceb5998 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 5dd7b0bf..269b25e9 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 @@ class TemplateProcessor */ 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 049/148] 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 bceb5998..d1c35b40 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 050/148] 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 762bf560..2dca8348 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 8e155ca2..0ec0ec38 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 c4be7c9e..ba41aa54 100644 --- a/samples/Sample_09_Tables.php +++ b/samples/Sample_09_Tables.php @@ -27,7 +27,7 @@ $section->addTextBreak(1); $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 09d32dbb..511e9081 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -426,6 +426,7 @@ abstract class AbstractPart $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 00000000..3d947bce --- /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 @@ class Table extends Border } } + /** + * @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 @@ class Table extends Border */ 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 e2e8f978..14226212 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 @@ class Table extends AbstractStyle $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 @@ class Table extends AbstractStyle $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 @@ class Table extends AbstractStyle } } - /** - * 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 @@ class Table extends AbstractStyle } } + /** + * 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 ce59f4c3..4375df47 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 @@ class StyleTest extends AbstractTestReader $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 dafdeb31..9dec422e 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 @@ class TableTest extends \PHPUnit\Framework\TestCase $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 @@ class TableTest extends \PHPUnit\Framework\TestCase $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 @@ class TableTest extends \PHPUnit\Framework\TestCase 'alignment' => JcTable::CENTER, 'width' => 100, 'unit' => 'pct', + 'layout' => Table::LAYOUT_FIXED, ); foreach ($attributes as $key => $value) { $set = "set{$key}"; @@ -174,13 +185,14 @@ class TableTest extends \PHPUnit\Framework\TestCase } /** - * 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 a89dd610..c0a0b3ad 100644 --- a/tests/PhpWord/Writer/Word2007/Style/TableTest.php +++ b/tests/PhpWord/Writer/Word2007/Style/TableTest.php @@ -55,4 +55,25 @@ class TableTest extends \PHPUnit\Framework\TestCase $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 051/148] 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 2dca8348..406122b6 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 689ac3d3..774fd284 100644 --- a/samples/Sample_14_ListItem.php +++ b/samples/Sample_14_ListItem.php @@ -67,6 +67,8 @@ $listItemRun->addText(' in bold', array('bold' => true)); $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 4a5f83f5..507ff143 100644 --- a/src/PhpWord/Element/AbstractContainer.php +++ b/src/PhpWord/Element/AbstractContainer.php @@ -207,7 +207,7 @@ abstract class AbstractContainer extends AbstractElement '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 971776ff..1841616e 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -415,6 +415,10 @@ class Html } } + /** + * @param bool $isOrderedList + * @return array + */ private static function getListStyle($isOrderedList) { if ($isOrderedList) { @@ -547,13 +551,13 @@ class Html 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 c281f998..8675ed7b 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 @@ class Cell extends Border */ 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 052/148] 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 406122b6..f6f87158 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 511e9081..1d610516 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -138,14 +138,15 @@ abstract class AbstractPart $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 67c2eb13..c2648b68 100644 --- a/tests/PhpWord/Reader/Word2007/ElementTest.php +++ b/tests/PhpWord/Reader/Word2007/ElementTest.php @@ -43,4 +43,44 @@ class ElementTest extends AbstractTestReader $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 053/148] 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 c7d8670b..17ba04b5 100644 --- a/src/PhpWord/Writer/HTML/Element/Table.php +++ b/src/PhpWord/Writer/HTML/Element/Table.php @@ -40,18 +40,59 @@ class Table extends AbstractElement $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 054/148] 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 17ba04b5..30de2397 100644 --- a/src/PhpWord/Writer/HTML/Element/Table.php +++ b/src/PhpWord/Writer/HTML/Element/Table.php @@ -40,21 +40,22 @@ class Table extends AbstractElement $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 @@ class Table extends AbstractElement // 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 055/148] 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 1841616e..73635807 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -486,8 +486,9 @@ class Html 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 ac68b887..8be1cc19 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -418,4 +418,14 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $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 056/148] 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 f6f87158..c684a37d 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 ec9dbe25..9c37dffe 100644 --- a/samples/Sample_27_Field.php +++ b/samples/Sample_27_Field.php @@ -20,6 +20,7 @@ $section->addField('PAGE', array('format' => 'Arabic')); $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 = $section->addTextRun(array('alignment' => \PhpOffice\PhpWord\SimpleTy $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 7b33a479..5aeffbc1 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 @@ class Field extends AbstractElement 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 8bfb3ac5..03fb692c 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 @@ class Font extends AbstractStyle 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 75d4983f..336a4325 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 @@ class Field extends Text $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 @@ class Field extends Text 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 ecaad416..a13db155 100644 --- a/src/PhpWord/Writer/Word2007/Style/Font.php +++ b/src/PhpWord/Writer/Word2007/Style/Font.php @@ -135,6 +135,9 @@ class Font extends AbstractStyle $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 f91a8479..887e8e58 100644 --- a/tests/PhpWord/Writer/Word2007/ElementTest.php +++ b/tests/PhpWord/Writer/Word2007/ElementTest.php @@ -322,6 +322,37 @@ class ElementTest extends \PHPUnit\Framework\TestCase $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 057/148] 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 1d610516..70d3d960 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -241,9 +241,11 @@ abstract class AbstractPart 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 c2648b68..6804b172 100644 --- a/tests/PhpWord/Reader/Word2007/ElementTest.php +++ b/tests/PhpWord/Reader/Word2007/ElementTest.php @@ -83,4 +83,22 @@ class ElementTest extends AbstractTestReader $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 058/148] 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 538d9c03..bb943d7e 100644 --- a/src/PhpWord/Writer/AbstractWriter.php +++ b/src/PhpWord/Writer/AbstractWriter.php @@ -216,7 +216,7 @@ abstract class AbstractWriter implements WriterInterface 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 059/148] 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 70d3d960..c69f636a 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -241,14 +241,18 @@ abstract class AbstractPart 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 6804b172..aad4a543 100644 --- a/tests/PhpWord/Reader/Word2007/ElementTest.php +++ b/tests/PhpWord/Reader/Word2007/ElementTest.php @@ -91,7 +91,9 @@ class ElementTest extends AbstractTestReader { $documentXml = ' + One + Two '; @@ -99,6 +101,6 @@ class ElementTest extends AbstractTestReader $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 060/148] 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 c8fe57cf..291a6d60 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 d63b7bb2..281c2630 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 c684a37d..7f527746 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 d13abc56..4d1b9383 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 f99b73ea..86e8e28c 100644 --- a/samples/Sample_17_TitleTOC.php +++ b/samples/Sample_17_TitleTOC.php @@ -12,13 +12,14 @@ $section = $phpWord->addSection(); // 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 61709a50..d49967ca 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 @@ abstract class AbstractCollection * Get item by index * * @param int $index - * @return mixed + * @return \PhpOffice\PhpWord\Element\AbstractContainer */ public function getItem($index) { @@ -60,7 +60,7 @@ abstract class AbstractCollection * Set item. * * @param int $index - * @param mixed $item + * @param \PhpOffice\PhpWord\Element\AbstractContainer $item */ public function setItem($index, $item) { @@ -72,7 +72,7 @@ abstract class AbstractCollection /** * 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 507ff143..1cedbef0 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 @@ abstract class AbstractContainer extends AbstractElement 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 2eceb5ed..8d4e0af5 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 7f665b1b..cb55c5ae 100644 --- a/src/PhpWord/Element/ListItem.php +++ b/src/PhpWord/Element/ListItem.php @@ -62,7 +62,7 @@ class ListItem extends AbstractElement // 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 808af55e..ed06fa13 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 d7c2348a..54ef65ac 100644 --- a/src/PhpWord/PhpWord.php +++ b/src/PhpWord/PhpWord.php @@ -212,6 +212,21 @@ class PhpWord 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 1d610516..f8a26ddb 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 @@ abstract class AbstractPart { // 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 @@ abstract class AbstractPart 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 @@ abstract class AbstractPart } } + /** + * 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 @@ abstract class AbstractPart } 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 @@ abstract class AbstractPart return $possibleAttribute; } } - } else { - return $attributes; } - return null; + return $attributes; } /** @@ -578,7 +607,7 @@ abstract class AbstractPart */ 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 61988723..b69b2606 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 @@ class Footnotes extends AbstractPart $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 1939aaba..017b3290 100644 --- a/src/PhpWord/Style.php +++ b/src/PhpWord/Style.php @@ -95,7 +95,13 @@ class Style */ 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 f204ab16..80c0904d 100644 --- a/src/PhpWord/Writer/Word2007/Element/Title.php +++ b/src/PhpWord/Writer/Word2007/Element/Title.php @@ -47,27 +47,36 @@ class Title extends AbstractElement $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 + $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(); + } - // Bookmark end - $xmlWriter->startElement('w:bookmarkEnd'); - $xmlWriter->writeAttribute('w:id', $bookmarkRId); - $xmlWriter->endElement(); - - $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 1cc94806..03855f03 100644 --- a/src/PhpWord/Writer/Word2007/Part/Styles.php +++ b/src/PhpWord/Writer/Word2007/Part/Styles.php @@ -180,9 +180,15 @@ class Styles extends AbstractPart // 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 20f0f0f7..867f680a 100644 --- a/tests/PhpWord/Element/SectionTest.php +++ b/tests/PhpWord/Element/SectionTest.php @@ -162,4 +162,35 @@ class SectionTest extends \PHPUnit\Framework\TestCase $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 3ea6242f..e99a80a6 100644 --- a/tests/PhpWord/Element/TitleTest.php +++ b/tests/PhpWord/Element/TitleTest.php @@ -45,4 +45,25 @@ class TitleTest extends \PHPUnit\Framework\TestCase $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 c2648b68..10c1ec9a 100644 --- a/tests/PhpWord/Reader/Word2007/ElementTest.php +++ b/tests/PhpWord/Reader/Word2007/ElementTest.php @@ -36,9 +36,9 @@ class ElementTest extends AbstractTestReader '; - $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 @@ class ElementTest extends AbstractTestReader '; - $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 00000000..0f7ecc7c --- /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 4375df47..c0d5d864 100644 --- a/tests/PhpWord/Reader/Word2007/StyleTest.php +++ b/tests/PhpWord/Reader/Word2007/StyleTest.php @@ -37,9 +37,9 @@ class StyleTest extends AbstractTestReader '; - $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 @@ class StyleTest extends AbstractTestReader '; - $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 887e8e58..b59e369f 100644 --- a/tests/PhpWord/Writer/Word2007/ElementTest.php +++ b/tests/PhpWord/Writer/Word2007/ElementTest.php @@ -447,6 +447,9 @@ class ElementTest extends \PHPUnit\Framework\TestCase $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 @@ class ElementTest extends \PHPUnit\Framework\TestCase $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 6998e717..39db6028 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\Jc; 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 f138ac76..348cab98 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 061/148] 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 7f527746..1c52179c 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 0ec0ec38..b84f76f0 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 f8a26ddb..b4610d28 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -422,6 +422,7 @@ abstract class AbstractPart '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 03fb692c..3095b799 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 @@ class Font extends AbstractStyle 'scale' => $this->getScale(), 'spacing' => $this->getSpacing(), 'kerning' => $this->getKerning(), + 'position' => $this->getPosition(), ), 'paragraph' => $this->getParagraph(), 'rtl' => $this->isRTL(), @@ -926,4 +937,27 @@ class Font extends AbstractStyle { 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 a8e1c69d..bb684409 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 @@ class Frame extends AbstractStyle 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 7e33f75e..32a22a13 100644 --- a/src/PhpWord/Writer/Word2007/Element/Image.php +++ b/src/PhpWord/Writer/Word2007/Element/Image.php @@ -19,6 +19,9 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Element; 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 @@ class Image extends AbstractElement $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 a13db155..5f2a84c0 100644 --- a/src/PhpWord/Writer/Word2007/Style/Font.php +++ b/src/PhpWord/Writer/Word2007/Style/Font.php @@ -151,6 +151,9 @@ class Font extends AbstractStyle $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 c0d5d864..ad8f125a 100644 --- a/tests/PhpWord/Reader/Word2007/StyleTest.php +++ b/tests/PhpWord/Reader/Word2007/StyleTest.php @@ -66,4 +66,28 @@ class StyleTest extends AbstractTestReader $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 d36a3037..f66cf24f 100644 --- a/tests/PhpWord/Writer/Word2007/Style/FontTest.php +++ b/tests/PhpWord/Writer/Word2007/Style/FontTest.php @@ -65,4 +65,19 @@ class FontTest extends \PHPUnit\Framework\TestCase $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 062/148] 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 1c52179c..cdc4d67c 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 99d8b3ba..f40a08c3 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 b84f76f0..b4ed328d 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 5aeffbc1..de504965 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 @@ class Field extends AbstractElement 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 728cc823..8ab58609 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 @@ class Settings { $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 54ef65ac..ff23f6ef 100644 --- a/src/PhpWord/PhpWord.php +++ b/src/PhpWord/PhpWord.php @@ -242,6 +242,17 @@ class PhpWord 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 b4610d28..2cbfba37 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -364,20 +364,21 @@ abstract class AbstractPart $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 @@ abstract class AbstractPart * * @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 581a546d..ee057fe6 100644 --- a/src/PhpWord/Reader/Word2007/Settings.php +++ b/src/PhpWord/Reader/Word2007/Settings.php @@ -29,7 +29,18 @@ use PhpOffice\PhpWord\Style\Language; */ 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 @@ class Settings extends AbstractPart $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 73635807..2c7cf1b5 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -252,7 +252,7 @@ class Html $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 7e40d9e4..53a9b958 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 @@ class Paragraph extends Border 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 @@ class Paragraph extends Border 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 19d3e54a..f91ad544 100644 --- a/src/PhpWord/Writer/ODText/Part/Content.php +++ b/src/PhpWord/Writer/ODText/Part/Content.php @@ -222,8 +222,8 @@ class Content extends AbstractPart * 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 @@ class Content extends AbstractPart /** * 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 e56e2612..463ce082 100644 --- a/src/PhpWord/Writer/Word2007/Part/Settings.php +++ b/src/PhpWord/Writer/Word2007/Part/Settings.php @@ -149,12 +149,16 @@ class Settings extends AbstractPart $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 @@ class Settings extends AbstractPart * 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 @@ class Settings extends AbstractPart } } + /** + * @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 8915fb4c..eeccc5c8 100644 --- a/src/PhpWord/Writer/Word2007/Style/Paragraph.php +++ b/src/PhpWord/Writer/Word2007/Style/Paragraph.php @@ -112,6 +112,9 @@ class Paragraph extends AbstractStyle //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 867f680a..37096e2d 100644 --- a/tests/PhpWord/Element/SectionTest.php +++ b/tests/PhpWord/Element/SectionTest.php @@ -184,11 +184,11 @@ class SectionTest extends \PHPUnit\Framework\TestCase 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 50863561..07dc8962 100644 --- a/tests/PhpWord/Metadata/SettingsTest.php +++ b/tests/PhpWord/Metadata/SettingsTest.php @@ -172,4 +172,58 @@ class SettingsTest extends \PHPUnit\Framework\TestCase $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 f8a22459..3b1b5a36 100644 --- a/tests/PhpWord/PhpWordTest.php +++ b/tests/PhpWord/PhpWordTest.php @@ -171,4 +171,58 @@ class PhpWordTest extends \PHPUnit\Framework\TestCase $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 ad8f125a..93e4a1f0 100644 --- a/tests/PhpWord/Reader/Word2007/StyleTest.php +++ b/tests/PhpWord/Reader/Word2007/StyleTest.php @@ -81,9 +81,9 @@ class StyleTest extends AbstractTestReader '; - $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 e961f36a..adf0ed4d 100644 --- a/tests/PhpWord/Style/ParagraphTest.php +++ b/tests/PhpWord/Style/ParagraphTest.php @@ -67,23 +67,24 @@ class ParagraphTest extends \PHPUnit\Framework\TestCase $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 50b444b8..a45253a2 100644 --- a/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php +++ b/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php @@ -330,4 +330,68 @@ class SettingsTest extends \PHPUnit\Framework\TestCase $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 9bc2756b..1e5e1d13 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 @@ class ParagraphTest extends \PHPUnit\Framework\TestCase $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 063/148] 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 463ce082..118c0da0 100644 --- a/src/PhpWord/Writer/Word2007/Part/Settings.php +++ b/src/PhpWord/Writer/Word2007/Part/Settings.php @@ -174,11 +174,8 @@ class Settings extends AbstractPart 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 064/148] 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 a45253a2..41583e37 100644 --- a/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php +++ b/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php @@ -174,7 +174,7 @@ class SettingsTest extends \PHPUnit\Framework\TestCase $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 @@ class SettingsTest extends \PHPUnit\Framework\TestCase $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 @@ class SettingsTest extends \PHPUnit\Framework\TestCase $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 @@ class SettingsTest extends \PHPUnit\Framework\TestCase $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 @@ class SettingsTest extends \PHPUnit\Framework\TestCase $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 @@ class SettingsTest extends \PHPUnit\Framework\TestCase $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 @@ class SettingsTest extends \PHPUnit\Framework\TestCase $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 @@ class SettingsTest extends \PHPUnit\Framework\TestCase $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 065/148] 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 41583e37..a8c01da0 100644 --- a/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php +++ b/tests/PhpWord/Writer/Word2007/Part/SettingsTest.php @@ -196,6 +196,22 @@ class SettingsTest extends \PHPUnit\Framework\TestCase $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 @@ class SettingsTest extends \PHPUnit\Framework\TestCase $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 066/148] 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 d1c35b40..742e4bc8 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 067/148] 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 e09421e0..c8152f50 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 068/148] 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 cdc4d67c..0c83ac35 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 4d1b9383..4c5ad03b 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 b4ed328d..98088e78 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 ba41aa54..e458a5ee 100644 --- a/samples/Sample_09_Tables.php +++ b/samples/Sample_09_Tables.php @@ -1,4 +1,7 @@ addText('This cell contains nested table.'); $innerCell = $cell->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 f6086357..31e5984f 100644 --- a/samples/Sample_26_Html.php +++ b/samples/Sample_26_Html.php @@ -4,6 +4,7 @@ include_once 'Sample_Header.php'; // 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 .= '

            היי, זה $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 2cbfba37..7ba53ad1 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -462,12 +462,42 @@ abstract class AbstractPart $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 8aba172a..92a24dde 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 @@ class Table extends Border 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 00000000..7cb0a0be --- /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 14226212..058e60e2 100644 --- a/src/PhpWord/Writer/Word2007/Style/Table.php +++ b/src/PhpWord/Writer/Word2007/Style/Table.php @@ -80,6 +80,11 @@ class Table extends AbstractStyle $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 00000000..14fa6a0d --- /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 93e4a1f0..3b04b677 100644 --- a/tests/PhpWord/Reader/Word2007/StyleTest.php +++ b/tests/PhpWord/Reader/Word2007/StyleTest.php @@ -20,6 +20,7 @@ namespace PhpOffice\PhpWord\Reader\Word2007; 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 @@ class StyleTest extends AbstractTestReader $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 00000000..77b22e4e --- /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 9dec422e..1ee718df 100644 --- a/tests/PhpWord/Style/TableTest.php +++ b/tests/PhpWord/Style/TableTest.php @@ -195,4 +195,17 @@ class TableTest extends \PHPUnit\Framework\TestCase $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 c0a0b3ad..2b67507a 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 @@ class TableTest extends \PHPUnit\Framework\TestCase $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 069/148] 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 362e8b74..740e3d04 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 d49967ca..899ec287 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 7210fb03..b5ffd5f4 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 56d92c94..aa807d1e 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 f2fe82d9..b6c02d39 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 52a56d31..db01b408 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 63989f53..a0a31ca4 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 9e4f12cd..1ea58ec0 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 8cb3a869..e42c9f9d 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 6a915da1..4f8dafe3 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 3fc16298..92ea05ea 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 1cedbef0..ec990720 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 e1b705e0..5ff85b8f 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 8d4e0af5..16b020d7 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 b5250cd6..68f5df62 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 c340da40..755f45e1 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 e0a94fdf..f3e87176 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 205ff598..96ad15ef 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 b6e94fba..b9627195 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 de504965..5171e9a6 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 08ff525a..0290d7c1 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 e9a1bfc2..90aabccc 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 598d61dc..f937df59 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 ee820877..8a01946e 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 5e73d4e4..03637067 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 eba66473..7e40b940 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 4637120a..2bec32dd 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 cb55c5ae..8b064c47 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 e311dc24..6e48a690 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 5da94c3a..c0c7f217 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 e41e807b..1e2ada80 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 ad20d7a3..1ce2dcdd 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 2e89b354..da4dfe5d 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 86f445cc..a866d1bd 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 06acf1f9..d612fc01 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 b553a4ac..d143c9b6 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 e3ca0a08..c51d0e6b 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 3a045031..10c4db69 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 4de12176..f4d7f081 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 8058d0c9..b9f274d6 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 4cf65f35..385fec5a 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 6d9ae9f4..9af55d46 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 ed06fa13..569cea92 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 dde616cc..410ffb7c 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 8207e2c6..1575c069 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 1ef35c1b..deb2cfbc 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 2f4e12ec..f69aad82 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 35f91ada..b8e0b216 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 81cedaa9..a769c5e1 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 a5c1da6a..d1c3bd01 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 fafc8dac..c8a06429 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 b94ed1be..d874625c 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 0a7b8fed..07c96681 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 54015506..d8fef961 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 e697f6cf..58c1961d 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 73b41d04..ee270653 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 eed1f163..3929f485 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 d9879010..cc1b2903 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 69f6f98a..bf0363aa 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 09714f9e..27ef89ae 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 39ebc3de..584ed83e 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 8ab58609..b1552e02 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 ff23f6ef..6b6fd9ff 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 f59a9556..7db285f7 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 4e8b5e82..db9f2089 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 c134377a..d4945229 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 5a22b4ba..0b58dc50 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 bdac3b6f..ff664e01 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 7a7a0468..9dfd6453 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 98832d17..8801a543 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 2d09a04d..620252ff 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 be16d707..b9509d71 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 3b2e357b..4024cdb3 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 6c2178ad..deed3ce3 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 7ba53ad1..342d9d11 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 df34c9c3..decc5103 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 f82c6b4b..36eecebe 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 a3d6b90b..a6835aac 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 ff094bcc..4e37541b 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 0f46cb2f..aa8b65d7 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 b69b2606..634f4739 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 c2a81dd5..3f57cbf8 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 ee057fe6..5cfe5453 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 8719641e..f343ad92 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 22b8ba1f..8de1a8df 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 442d8251..f2375d87 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 56687c98..c53f0030 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 2c7cf1b5..15f3b605 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 1c7b4c6c..fc0c7ecd 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 bcdda0c3..2e6a899e 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 3d8d0a41..2783e17e 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 cffa0003..e386913d 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 5d0ee33b..e55f824d 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 71e07397..924a4f20 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 f2cc5e63..8fd8340c 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 480d8539..83da66fa 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 3d947bce..7fd753de 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 de36b108..838b0c5e 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 111e4ea1..02c38fdb 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 017b3290..47242621 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 76ebd591..8edbe80b 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 ab6aef18..d032d07f 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 8675ed7b..e609e190 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 694fcddc..58271fef 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 11c03eda..4c860bcd 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 9b473009..360bcf3f 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 3095b799..c58cee49 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 bb684409..b9263049 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 e0b97215..70aafe12 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 9621714c..e422395c 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 e09421e0..91f948f5 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 16d15950..a9952eec 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 b5f3c263..451252d8 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 444341dc..306ecff3 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 80ed5dca..f7855cfa 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 33c151e4..e9b32f01 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 fb7e028a..a04ad974 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 09e4769e..3c93ed8f 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 53a9b958..ac587686 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 b56c6f5f..ad801af6 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 476846f5..162e08e0 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 eeb055b2..154df26c 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 71d1e3e0..1379a320 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 fc84241d..0c3f8179 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 489eb5d7..9bfb2282 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 938e6de1..2efd54a4 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 09e49e02..d3cf5bd7 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 92a24dde..feb028da 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 7cb0a0be..d4b70831 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 91adc0af..e9c0f0c0 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 a4769927..c42696f0 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 269b25e9..72446ae7 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 bb943d7e..7e0d511a 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 9b098dd8..7f55b9d3 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 47f0f93c..dc5ccfaa 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 649cc7b8..082bd760 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 677b6173..006b5889 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 c4a3e436..2252dc3a 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 60b246f8..ed14db1e 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 3e516b53..7c22a166 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 f29880d4..f6dae5cd 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 02b25eb9..384b3ef1 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 5cab2724..f9998e37 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 c7d8670b..95f7c1fa 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 9f8f7773..04d76a83 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 93ab924a..6ff092db 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 d7461539..b2deaf25 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 ee8f271b..3a802018 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 7b6e0c3e..2d86f399 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 eea17350..a029f965 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 f4d63014..1107becf 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 fa27c085..cfb54cb8 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 8daa8823..1aeaa347 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 73830707..ee5d0896 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 178b1434..93747b46 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 57e44e85..863ef93b 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 7158874c..efd0d6a9 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 481995ff..9c9fc1c4 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 112e71e8..6ba8124f 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 2c0b4727..add45e10 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 34d72c1a..d6fec507 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 6eee6cfc..ecf47607 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 cdc2a0e3..8a21ee1b 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 f9259fc5..7dcd28a0 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 f7642e3b..80cd1387 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 f5c855fe..78e5a8ad 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 769d293f..343949a2 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 74412fd4..f2844de6 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 f91ad544..a50eea7b 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 d916ccdf..f952b4c0 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 f592c5f0..f38ad01d 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 6e45b848..552f5440 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 e49fa25e..e7635e98 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 26b9905b..f7679ab2 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 50de32ad..7c7d20dd 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 b85d4d70..13005a7f 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 14a811a5..223d02f0 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 bef023e9..92d88911 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 7d66899a..249321cf 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 45fe8f35..64dcc789 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 7b668e0b..5f9e3b3a 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 be282d20..5fa8f75d 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 b6980a9d..e63f5dfd 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 85e3614c..badab046 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 7756253a..0604e8b5 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 1013ee36..cf1aa391 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 4850c8bf..58c19256 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 fb96baff..f1e72700 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 91a75720..25954ed8 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 e628bffd..29e7f660 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 0adbe06e..6b08c9cc 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 d0bc0845..8154aa7c 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 2fac0520..f80e7935 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 2009fcff..4aab2767 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 d4e56765..bfd161f0 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 18bad9fd..a9940ca9 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 7569a105..8171b0d2 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 465872ea..d4bfadb4 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 73f1351f..01439bc6 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 80523610..57aa6bb9 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 0ba9f602..08dcf018 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 3338368a..8c729425 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 61b61fd7..3b8690cd 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 8f073716..5c34fa86 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 fcef982f..eee215be 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 8c9f0bb7..63f45a76 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 4b0b78a7..04eaacf3 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 591799ab..f88ca2d2 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 ab888f67..05692a07 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 b6d1145c..892da051 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 ebfe35c1..9a2eb3ff 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 336a4325..cf3fbd66 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 65ef40c7..56a5332f 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 c77ca378..b59cf58f 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 32a22a13..3614ec18 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 9b1a160d..a114be60 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 dc708a61..f0adf851 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 c1aa0ce3..ef738e10 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 e6ed2b46..765d2ee0 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 50891d97..c55ff6cd 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 04ff29d4..0801e4d3 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 0dafa4a0..5563f607 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 13887866..94ce6ede 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 6a202564..21020a0f 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 9f111293..250d5c1d 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 36ed7f88..94437cbf 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 c0590772..25a48ab2 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 44450fd6..f44e9ebe 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 130b912b..f421c1af 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 3780c698..9dd4bc3e 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 161a528e..7b3d9997 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 9fd70b13..e46ad3f5 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 80c0904d..858ecfef 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 038eb21d..ce4e41cb 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 c3703f9f..3db542c5 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 2b8f9267..33c9f59e 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 9be988d3..28a2d294 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 dbd55187..3452d864 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 fdabee36..caefbd86 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 8ee2f028..478075d3 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 72e4fcd8..986b4985 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 289119db..ce3a46bf 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 065a318e..1161a951 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 cfc9dd40..97b47790 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 c9e3bcac..59bf1830 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 5853d92f..b58df1f9 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 6233a6b7..61e5cc23 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 154c7e89..661a4fa8 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 505aa223..2a0c5e11 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 e639c041..ac61a0c2 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 118c0da0..42d3a5d5 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 03855f03..d05338c7 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 c264140e..f4ef478e 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 9f18e356..46252e87 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 d7756933..3236cead 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 b889aa55..733b7b43 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 e3a86a58..19399348 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 de64313b..53d03974 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 5f2a84c0..58282d15 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 9bd5db66..47f9ef75 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 271b99df..ef23ed10 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 c5a598ff..961e770f 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 f065e521..154a42c1 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 3ed577c6..4bf08b65 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 5c3ecde2..f5c4b015 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 9ae61f39..ae4c1da3 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 eeccc5c8..67616086 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 f57094db..82028d24 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 ef50c111..af77396d 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 00680687..0f9d6ccc 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 5efc38c4..7fcb12a9 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 aad42ae7..2def6842 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 c18339bd..0185cbcc 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 7b0a0ab5..b41653f6 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 058e60e2..eb5af86d 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 14fa6a0d..fa57b93c 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 cd92f845..627d0c86 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 b5f08199..499cde3b 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 a8757171..aba63212 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 b8df9bbe..4448daf8 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 baf2009e..cd1e77f7 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 87bb5e18..f0531b34 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 bd5d27ae..04e3f6d5 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 a1132cfa..d4aaa488 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 d5bda9bd..f732407b 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 d33a54f6..b9c3dfce 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 8baa68e4..1c1c0ca1 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 b68e80cd..9de2487a 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 fd4c8d03..4ea330f5 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 29b2fef5..e61175f1 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 8bebce91..747a77ac 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 4d414944..20eee74f 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 63e8f1de..e1be7521 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 84beec02..95eb17eb 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 5fae34d4..e5c815ec 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 ba761b70..9fbe1bb5 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 3b081848..d4491fe1 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 c2767a4f..97e49b93 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 9abf3776..3c534502 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 41eae213..6e40bae0 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 37096e2d..265307d7 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 d826a1a1..5f5f518f 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 0bbefb24..8ae5306c 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 63b093c9..cd50acd4 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 9b25bac3..13084c67 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 59b8b89f..2168bcc4 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 09027ad6..97be7ae5 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 e99a80a6..6ef87c3e 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 3249f10b..df86feb2 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 fa9949ed..5fed9c9f 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 6b4d14bf..f879285e 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 255477f9..8c7bce57 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 c0285dc1..71da1aa9 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 d516019f..1d981449 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 559d6341..5b03f5e3 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 581b7d49..4a59e702 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 ed56376b..02492016 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 d9b44dc6..25a323d2 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 07dc8962..9670f1d9 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 3b1b5a36..d818e0f8 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 c56fc1fc..38588afc 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 e407547d..3ce39939 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 7041e13e..ad270864 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 ca1f6ed4..fed00ceb 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 10c1ec9a..941e6f82 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 0f7ecc7c..31a492b8 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 3b04b677..46421d97 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 9a555672..62d23a68 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 d8752b2b..afe59549 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 752b9a8a..3798a07b 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 8be1cc19..7541c9c4 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 c42a6eb4..5a050c54 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 cb095127..ecd0961e 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 c0263b1b..7ec272bb 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 79b22ee1..db789fdc 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 91bba97f..4ddbd397 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 5d9e5568..09287bb9 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 63a96628..b39a4d77 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 74b2067a..99741cea 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 9ec1e3b7..0d3f4e05 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 ab77b328..fba09f70 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 a8155fa3..71598e80 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 9b512eb0..008a1fc5 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 4ec12366..2090f9f6 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 687e23c6..688f31af 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 adf0ed4d..62460738 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 2daad7ea..534815b1 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 c9b7003f..b26d1d94 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 ab991a57..7aba03a1 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 65be8092..f7402edd 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 5981b00c..445c5e43 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 c11f0558..8d8d3f6c 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 1ee718df..332d31aa 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 5a6bc76f..803189cd 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 6f2f0980..cbc39c87 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 7b064ef7..c762a609 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 fc092ba3..ff79953c 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 3d56f983..f8303414 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 e9117de9..5b60226c 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 f2bc7175..8868db5a 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 f56114ea..37f0d1ef 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 f91e6dd2..51d893d2 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 d5681143..2e501c60 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 5bd862f9..b1bf417d 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 1984de0f..a576a68d 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 61c3d296..bc229d51 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 330125fb..34a5f8d8 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 e697eee1..6dc8f24c 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 a7ca9f68..f699385c 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 e85d2091..47630335 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 42f76430..5f04f1a8 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 803087e5..010720bd 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 b59e369f..979a4337 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 7796c02c..fac94882 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 83af284f..0233abdf 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 39db6028..b35f9327 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 82bb7b7d..1f9bba0d 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 3d11174a..4b0e94df 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 afa81cf9..9edd0063 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 62127e29..fb5a220e 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 a8c01da0..8201d746 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 0cdb444e..91f37184 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 160bf553..277f61e1 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 f66cf24f..c57f50ab 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 1e5e1d13..8443bbca 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 2b67507a..364a34d6 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 f48597d2..48cff871 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 3e1edb39..22a0e6df 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 348cab98..d9097d71 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 bef060ee..02fa7d78 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 21a12105..8c937bf5 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 7126c204..c1681bcd 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 070/148] 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 6c7033b0..f7be3be9 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 @@ $section->addImage( ); //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 @@ $section->addImage( ) ); +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 b9263049..e87b7a80 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 @@ class Frame extends AbstractStyle 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 47f9ef75..ea5abf78 100644 --- a/src/PhpWord/Writer/Word2007/Style/Frame.php +++ b/src/PhpWord/Writer/Word2007/Style/Frame.php @@ -45,10 +45,14 @@ class Frame extends AbstractStyle $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 @@ class Frame extends AbstractStyle '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 4ddbd397..6a934579 100644 --- a/tests/PhpWord/Style/FontTest.php +++ b/tests/PhpWord/Style/FontTest.php @@ -115,6 +115,7 @@ class FontTest extends \PHPUnit\Framework\TestCase '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 09287bb9..1d43d921 100644 --- a/tests/PhpWord/Style/ImageTest.php +++ b/tests/PhpWord/Style/ImageTest.php @@ -35,12 +35,16 @@ class ImageTest extends \PHPUnit\Framework\TestCase $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 @@ class ImageTest extends \PHPUnit\Framework\TestCase $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 ff79953c..ceb3abcb 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 @@ class ElementTest extends \PHPUnit\Framework\TestCase $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 00000000..efa0a105 --- /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 071/148] 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 0c83ac35..e4515131 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 98088e78..9b3ce758 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 ceb3abcb..b99a5c9a 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 072/148] 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 9d002623..7509a382 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 @@ abstract class AbstractPart $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 @@ abstract class AbstractPart */ 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); + if ('External' == $this->getTargetMode($docPart, $rId)) { + $imageSource = $target; + } else { + $imageSource = "zip://{$this->docFile}#{$target}"; + } + $parent->addImage($imageSource); } - } 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'); + } 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); + } + } 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)) { - 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 ($xmlReader->elementExists('w:br', $domNode)) { - $parent->addTextBreak(); - } - 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"; - } + $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 3a802018..7307ce0c 100644 --- a/src/PhpWord/Writer/HTML/Element/Title.php +++ b/src/PhpWord/Writer/HTML/Element/Title.php @@ -38,11 +38,17 @@ class Title extends AbstractElement } $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 343949a2..8b9440ab 100644 --- a/src/PhpWord/Writer/ODText/Element/Title.php +++ b/src/PhpWord/Writer/ODText/Element/Title.php @@ -37,7 +37,13 @@ class Title extends AbstractElement $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 f80e7935..b9e56e89 100644 --- a/src/PhpWord/Writer/RTF/Element/Text.php +++ b/src/PhpWord/Writer/RTF/Element/Text.php @@ -34,7 +34,7 @@ class Text extends AbstractElement /** @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 46780278..75060625 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 @@ class ElementTest extends AbstractTestReader $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 @@ class ElementTest extends AbstractTestReader $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 @@ class ElementTest extends AbstractTestReader '; - $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 46421d97..9bb6d3bd 100644 --- a/tests/PhpWord/Reader/Word2007/StyleTest.php +++ b/tests/PhpWord/Reader/Word2007/StyleTest.php @@ -117,10 +117,13 @@ class StyleTest extends AbstractTestReader $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 22a0e6df..0db36fc1 100644 --- a/tests/PhpWord/Writer/Word2007Test.php +++ b/tests/PhpWord/Writer/Word2007Test.php @@ -75,7 +75,7 @@ class Word2007Test extends \PHPUnit\Framework\TestCase 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 073/148] 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 e4515131..b58ec404 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 e5377cf4..0e5e28ed 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 074/148] 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 15f3b605..64c6b4a5 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -520,6 +520,12 @@ class Html 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 7541c9c4..eda7abb8 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -114,6 +114,34 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $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 075/148] update changelog [ci skip] --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b58ec404..e2bf4eb7 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 076/148] 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 31e5984f..d8763805 100644 --- a/samples/Sample_26_Html.php +++ b/samples/Sample_26_Html.php @@ -18,6 +18,9 @@ $html .= '

              היי, זה $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 64c6b4a5..dcf84778 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -521,7 +521,7 @@ class Html $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 @@ class Html 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 077/148] 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 dcf84778..f8b25605 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -521,7 +521,18 @@ class Html $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 @@ class Html 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 078/148] 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 eda7abb8..386aaee1 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -20,6 +20,8 @@ namespace PhpOffice\PhpWord\Shared; 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 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $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 079/148] 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 6b6fd9ff..d524adc7 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 386aaee1..1171489c 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -19,9 +19,9 @@ namespace PhpOffice\PhpWord\Shared; 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 77b22e4e..1243c3d5 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 080/148] 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 d524adc7..b5cc0c51 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 081/148] 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 f6f87158..526b9c95 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 ba41aa54..b1231d55 100644 --- a/samples/Sample_09_Tables.php +++ b/samples/Sample_09_Tables.php @@ -113,20 +113,20 @@ $phpWord->addTableStyle('Colspan Rowspan', $styleTable); $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 fc092ba3..eb0d2571 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 @@ class ElementTest extends \PHPUnit\Framework\TestCase $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 082/148] 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 7509a382..9623fb79 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -135,7 +135,7 @@ abstract class AbstractPart } } } - $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 @@ abstract class AbstractPart $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 @@ abstract class AbstractPart $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 083/148] 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 9623fb79..f64886cf 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -135,7 +135,7 @@ abstract class AbstractPart } } } - $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 @@ abstract class AbstractPart $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 @@ abstract class AbstractPart $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 084/148] 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 011e3472..09ce8c55 100644 --- a/src/PhpWord/Writer/Word2007/Part/Chart.php +++ b/src/PhpWord/Writer/Word2007/Part/Chart.php @@ -236,7 +236,7 @@ class Chart extends AbstractPart $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 085/148] 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 e345afda..87d6f3e3 100644 --- a/samples/Sample_32_Chart.php +++ b/samples/Sample_32_Chart.php @@ -49,8 +49,14 @@ $section = $phpWord->addSection(array('colsNum' => 2, 'breakType' => 'continuous $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 09ce8c55..59255a6b 100644 --- a/src/PhpWord/Writer/Word2007/Part/Chart.php +++ b/src/PhpWord/Writer/Word2007/Part/Chart.php @@ -280,7 +280,7 @@ class Chart extends AbstractPart } $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 086/148] 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 9c3b4dfd..d0b39ce1 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 ee811b00..c7ed27d7 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 4c5ad03b..8f33b503 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 9b3ce758..0bda3faf 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 087/148] 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 59255a6b..2aeccca0 100644 --- a/src/PhpWord/Writer/Word2007/Part/Chart.php +++ b/src/PhpWord/Writer/Word2007/Part/Chart.php @@ -236,7 +236,7 @@ class Chart extends AbstractPart $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 088/148] 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 03637067..0eb3d937 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 @@ class Image extends AbstractElement 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 f64886cf..d8155eb5 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -260,6 +260,15 @@ abstract class AbstractPart } $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 089/148] 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 00000000..44ee07cd --- /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 090/148] 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 742e4bc8..6dc9be2c 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 ec990720..204d4a73 100644 --- a/src/PhpWord/Element/AbstractContainer.php +++ b/src/PhpWord/Element/AbstractContainer.php @@ -35,7 +35,7 @@ namespace PhpOffice\PhpWord\Element; * @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 0eb3d937..bae87ff5 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 @@ class Image extends AbstractElement 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 d8155eb5..c7ec4ca7 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -261,7 +261,12 @@ abstract class AbstractPart $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 @@ abstract class AbstractPart 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 44ee07cd..00000000 --- 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 75060625..cb72ef9f 100644 --- a/tests/PhpWord/Reader/Word2007/ElementTest.php +++ b/tests/PhpWord/Reader/Word2007/ElementTest.php @@ -236,4 +236,40 @@ class ElementTest extends AbstractTestReader $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 62d23a68..e4ea62de 100644 --- a/tests/PhpWord/Reader/Word2007Test.php +++ b/tests/PhpWord/Reader/Word2007Test.php @@ -64,4 +64,18 @@ class Word2007Test extends \PHPUnit\Framework\TestCase $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 zoP4tqDzK~c(()KwS6(+UHoW6amEOB+g`{PvYa4M&)4gd}lu`7ny!2$1ld*U|{i!oW z^DQHN1HUnk#TH}GyM>q3AEBb4AOLUEy=rz(ms9LsUwzhzoaK)@c*@P07ieqK2BoGSRP`zf1QuA-nRw3kT5zC&*S{^9~Ep3t(mYTcj5b`FYw@6k> zlF-&&)@9lqi87kcN$`68`Ys=)bZH7$SV{17`S<*?x3pziukTdWPAKS9?fb#?)C<&V zP4mlmJqiUm1$1729@Z+!CzY=U0UZ$u8>Ud+eOjf~$vy6k^R9{XMUM!T-=)@5f#NcH z&2JO!DrW@b8=@zZh=l@_rX;m6BM!7U!OJY+rAbA18y>0~9$9-Al`(n5zn;@w{hm`I zLk#6=5YK~a6;I$$X}CzvBmSTSo3YfeCS$2H{mw9SvKK98Lo(HEz|rt=K<>e$<5clX zmWU+zV@@lwQ*}^XZ3C)$M;bXeH;^Tkwg)odgnWMpzJasQx~@dmy>Nt64Dlam?cGi78ZQ->u5C$(wYP!n?IkXUHlLTBGTKS zA<>WyCy(XV%5GJ-LR{@0kaslM!jhL!yA6J5k>rH1N4$~S??2d6$hCnAQtn3I?LjVx z)Ng5h%h>Mp3X9s=o62RV1(fqBOH94b5W!;%Lz3yp3>bxi2FResg{5;!2gG2faSY_= z(pS)FDv3B1Z7>%RCM4RJ`(8OcJ1rGZ8yWG#^JjaC^})ayA% zXd*t|X`nVNn6c-P2;Rm?ML4vq{sO7c@CpHRac&S9>vnF_IW zH;sv|d+@5s-k8*Yx$ERpn?6=_7%ro^s|(iO-)8HXlPqrrSPi9*n!w3{KZ8BI`E04t zXuiNmot~}v$l+g;w|~)QgYtqRZ6c0RGX$WwTwX~&U%bn%4ULt5hlzN&13 zN>mA+IgOjuzkbQy>DH#IkKWn<1SynD$w660zou4)cuJQ*=-)jsQwl}V?=UH~d`%sM z4i`)bAQFdkh=CWr>Y6ata$MACwyTki&L|H*Oyzi9hp-8(@Rw64Fmc?OxrMtw7z-40 z3uP5vR_cA<{k1!=2${d+qhHUM*Z=`zrnq+U{{3x3wqS5g-(4p9@PLVUa;-_DJX66W z3jUrAccamiG<6C&&VF^hEZojlc&UHPhPzB^4k3-5$^E=FRUHZ$9k#&@N1Uc1HwnO( z){0@~04sV`a0aX4U6>0Qh|GbPIZlL#>6waDI_Wk%_&NrONStcsj@=5pIt=@5zPv@O zy^X}|RszKT(`~Rmp&Xb}H&I!gEH^)_gKIG(aG5)iIM6y<9A(MWQ9G9(V8dI5=u%ZY#$xgTjs@*Ej!Ir!9>GMA;+O{OvM@# z7s%GG;jWUfZ(&zG?rQ9#hRd*JjcLb%t+}SH#d~OgM3lzMA8y&7fUqjf&T9aNdl^t9 zvk9XFfBYyom}s&XeJJ+8^3_E#8QA6q8${Em^$VV*^gNL6UiA}c z(u#GecP)j@Cj{>vc|ZUvY)N#`NXvC=b*U`1`JQ@m*K>Hxo(oK9ytrJ0%SS@X3psLf zO2YjY_I4_$=xCe2vj98Gi3#XE(@!MvM!p7?=@@%3e;|lbvofJnHn! zDoNWlLrBOU3gC{*QpwJcP{((7YozF(l6*ZB;qk<(ZFS7TD$j7!AVLhmJpF#$M<3Fx zd!5Y#=$-^AFxhnDtfvGhg9JPx0ne$(Kh~47t+tnhuNxLrz$Y2$Vqrkp3WkQs2HYT+ z-5@qvA5-@Tf$6o~KftG|RcI@)8%RJuYxgzYdr={{2~ z1yAn%qMWiS2vd1gpiwS>hRdw?lW#m(o zw_4WS;$%k-){i|$B$sPUO|%h8tzrJ<{xB`m8sB!Oy!Z(FXpirG(0g{gWeHWCF_g8A zzP*ctnIV+uyW3M=Nb|Nvx41Iw0#9f7)8@3yk(=NpoP5+5>B*KSxKXJs*ZAxRD%Ufqd4be$DXc#)Wu zd7ZGg;)(9A){ReJt&v22w=q$ZM>YEMwud|UC>5#T0Hvs_QMO@8l56r5s8#ZpvxslJ z<`d8A zF^$IZ9#wHG&!js#-#4IwbPhxfCC^;@E8;Bk)bNI~WZ&!rUkf?$aII@Y-i)qdsCkJPOpY_kx!92Nh}(*&g7IF^*}vZPoC1YUHtsxUuP*_4mPk^I8@OKz z23Gw?miLrg9W1%%c#qG~H>Tp1hMHpA;$v^5 ztkWJS;f|!LHYwaO?^tz__7;_5&UZD;_>uuhpI~`A)(XsRd7n}48)NWOuzq~m|FN#2%q1=;Ajfd@LZ3v_X8np^7*$iA8ol_ z8~LXoixq@FlPzK}VjY)Op8z*-9!uyzCB_e!c)c{E-b`}*sn&tP5kBngrt7{U;NX;8a!GzNhT-82;`V;`IR)8WBbIo&BT}s&;$qvHY-+KRiu!t~aQm zS(T>7Un*%^7tykLQq)@Hq~*b)i{vxhs3ufLK>sj#drG3!PW5Bj?Q!Y;+&=NO@yr{6 zS%B$s;*Mg#uC;MHq1QZT^PVvDYpu3zLSv^!)uQMxm&`7 zQ}x#SlG6HtJ#KFyt&(jd0rd zNFWFI(=31b1UT5V-1W3V=C1ZTPZ{9i%Ymo`HG}9beduFXO<7;X)$UF(nhZXXt3HTY z>rz57H_2e?iBg?6qrAz6RX&*_3b}~Hq|VN7egf=^HSZ?X4X-ER68>@}olnD*H3%1A3q%xsT47@qeiCXBe z#9KA^GI6uc8l=;-RCNxmnExKUnm|9JBv?%*3;ecP$G_j;(6WgW#oNCJD6cNgkaeF7 zt03>TG)Skc2R7JwOs>hB1odfkKPQ=*-)FtgjSsaA&BpJ_q-Ib6F4;5Fvv4rrAk)J4uV;ay6C!M?^jc=!h)C}^OcS~o3sH}BsO`rwAGVoXi)&9MTu6H0;%bd!|&sME)0!oBv}%9M5ZC=6?FxmR(xYV>lwJcbXz zUbj(GSAQFouRmmyW*kE4MQv9+=sj_QxT2Ag91a|h*Ng<@q*XE>Iq<$Hz7Dw9WnMDs z*$mg2MUlkvoD9$#oNMUU{!|EABdA=2IsXGjBT>_@**U>A=cKQI^pyrj6 z4HqG7nz>g(TH>ago+DJ4{DQ4Tn}06^uR+WSWbRI#Vo*K-{AOisPL~Su_!dZtM1au9 z(dfHhlx$Uxg%jE)*qMU}GVq3COhp%Qe){l~~oQIDoc0xrkE^_%fqzI2kLeLUY& zQ*}}Qi`SU9UwfXr59!t(7uRK*I!cde-8&)nASdA)0tPXZk-=Wc_7hD~i0|W{0DrKN@=&{-o^;ih6qBR#9Gx`?%-bjedr^aaNrYg+VjN@{(Iiw-@+&o zz)7Bu`Q_~U{U_k3=fq_L-U2iLs^=5%C*`piE;P^I#^wh4CeZY_!u+)FUMo!B%zBITjsl=F>cqE5)q#w#A1zfFYT^{f z0>o(i!_SczQ#hZk5~#%pkzaa+(6FXa=ib*aPZYEn(D-~QBLNVqnW7Dyj2Nhm6_kXwlet=a2+Ljv3(eF88W zsiw=X%G*=7i9PkMgur5jvuf`GV$zsFd&vZjf*<<;@Zyxp1*XLs^kReeJS@g~AK(B` z8KN#1Ja;n7dA1dQ&dPi)zyI6_@!$Wx=wTw{e>h>Vf6tiw#{rZtdiX!;qXtYub^mh0 z|Ll-Js-K|y`s{G_f4JQQ+l6SDBx{&GC4Y2^?htijUP;yS3qP~WjQM!yWIQ#C+4fHF zJazB{kY;hFEw}z^od4$b#YdywxYfi$YB8mN(Tj1AVxI+9J?X%3ybn(2T&?=DhR0?j zSu<9ERX&pWV9t?_u`t(~P9sE1?%?b*^&eYj>$xmlvhLRfB^uzL?Xz|7XY{mQJ~(S# zA0hTSEDGJl^3s7>!LtWjfGHt^N}?N9*m{`h*Aeql@3RN-?&pwf?J;SkoWYst9(Wlw z-Wc^;u)#RTcgOlj=4Cry!ZWHpw&;%K=;Lo1394nUkZ#N1Ua5s zSCmo1x%7zNHE3Y!XSwWW8Ec=;o~>+LZt>Uw+p0QO&ypbJEDqMJ3Eg)6`0H=j&X{<+ z3ysK*k`*|sxIAwhrrk)TU(KPwd88O7UChZ^mER=eyG9yxMvH&AB@4v<#gZr}Gh0d6 zVfeM>i=u%TchNzLd}3-5_Q(O#K;PkleY0wM&0rI8YUFCLas5*33PR}_W!raiyR_%d z%o1|iOyKsR2$Om1%Ec3D9+&`YXzYW;V!UqgaQ@0R)fA}`*6hXQMmEKsFdgNuFC z1^iMqw2U*ve&FRhrOt{?i!{qRC{L8aZl2zDZS0mX%^mS?*6MnY#mQ#zm6?HDZ+&<( zuMjP3)?ujcSfZ=M_zk4+8AV;+9os2u5JxCC>9YIn{~%qC*%-M)bUhkef)0C`iUy%* zL*%Pz3!-W2*CsqptV(DH5IXae&?M+=&f6j4A~R za72i58=e5k@kK^_at<{+_+8Ch9KWuSAt-8e)`#-3b$ZMrQ{97^)x2&)PtP^0>nd6J z^Udh_C+)?J%eqZb^SbpXVEGH&#QziA|GA&zzkyrPA@5&w|Fe+;>Di|FYU;h_jNEYD z<`ZB#(eD=P#iHAs)2gT|i$9QaiAZ=VP<=%ZuJ*2l#JS6G@hz9UB=&LXzUSzWyndjA z{qoq1Kz{4?#ONy3d7x)ELg{kzeZo8CyxjodlyLKb0B%Aq(xC3-xf++=B~UwLB*l*5 zqc_L}s=?WS-<}y}BzBegnc>^uxBVKWQ1GTKK>uAqG+Sl9+r0dhqV_|AvFi^u7O`@|tP21Ivw~59yM7l>FQ_s37!aHcn%DAM2YI|9bME zp6gKTCDu24RDB606>rPyE zyEg%Z;vaV-uEHuCC;Kq|M9%1K=ZT z-R-@7jE@ij9{; zwtyY_2@rtpl2ll+tsYx%UNFcs7G~{HO1mQ5UF{NVv2<17G2;JKI8yIz!|yPrkm9rj zfBckrG(cB>mB4SDu^L*p)uySp{M%*@Vv zvuEG_2m3>2ovO&lic_afWQJsX{~d|@)czQBZy2;HG)ea~Co1#5$`q8>Wn9KwX;sVY z(iN0*iUp*-{zWSJ95ZUl+CAuB_5m;;Dt5x9d1OKQn(F_(`GCkHW+vB5kTg%OsY`lP z^h-p6F!<2*TV{5i^WWabxCBXQsz13M>|DJ}Gw{M*E`o(mQ6*u21;0`xWmlgQl<-Qw z3EGQcynX;milv2A-ZPp%vyU)0H8llIZqeq1;QP0XOcw`V+XTVDrK`~ekq>ypI#++* zqJN27_-4%GwvQLl?B$opnTKHlRZ;DZw$yhx@1Qp!_V_Fr4YutEAAw@PK`8YU167%U zbq%LA5{k5)nmjRJ0NAN{6N)HbmWxz)9<94*t-jv;0Kj5ASP0azq{xu?vA*S3%oIHL zsv-Su)rqXtNg^6GWo%Sa9X4W0>1vO6iEnCozMxZ#0Umw;h)3x%-c8R^Le>60(vTuK zQC%|-2X@fC+yz4!*T%1fOJf9#3RdaPw!RfN%dKR+&p?l~v`b(QfJm0ne(NebzOtUV zZv3hm$u6$Zc!|Xgn9}oIl;OGxmp?IG81AR=wg&VQD3ZY zfzS%@!I)%rP{}J#QI<@&r2?9I{4%u04Q$F~GSYi@V^Y364_P08U)_(o5ISCAp;tZE z!-|zPFxk%$<)w!a(ne}fpf{t$N}DFowRa#%6Yc4{1Q1f+WgtQ+PjLW!KpU$#<42SB zYfn{cuXfV+XWk@m72aN}G zKL!0GqajB$@cmJolJN1W6=CT0)kNKT*{oJdec7%7jmS+z4s{6m?R7iCao2{(m*T+K zZiuy#sA4thbZsK2-k0^J2C+h4O19eHURPi%0SnEl|CaC**OFP%#1nJ>p_d%Lq)9cIRuvD~;-+ewSH z-5tW6|Jgmp0rxb?MB@5qUMbC^Pm@c+Iku&slsn(WJ*)W{yW#I-fu8M zWt+zict`_+0WXpok!s3u=f9vFQH4pgs>}$Q6FuN#r6s;;`sm65AwnDc-C0PRHS}dc zEGbVhd{86P&hWDDaijfjr3@&< zdu-_b8c)#o4zF|!3;xbQh#;WQr}s40;gKNGrfi4OnoFa6U;x{Wxj8C-cw8;0lHMtH zoLKp|1s}7nyN$ug-FtWz9lu$UAN43y!YOpwOp9IZQ`h0hC}PzWU<-5zBRJK+bs5$@ zSQt`!I|*kp{>d7eSDGq4D_Ma~NYcgQw*KB3z`3J1x|BmCAQPf~@&Q1Fgk|xe^4sPS z`Lv->gA$A0U`Gy zgY;;XbtKsaj13nW%Ys#u-y#yhvt!d%u}ngswT!HL*NV#5lBRwh7@X>+P2)lnqcj8S zuNgwK`K80Xubz_?HwI@VQ6kHPi4Y(Gup||GX*!l!Q7z3% zK+Dy&#z613%!Y#VNLv-dx$qyH?MtWwp*LB5J!lii5Ql~1BD_9hHP5Mqufg3j{m;2K z^ZFW&>BKvaP;SjSGC_2>FxtdLP!onZU(2Cdr&Q3vQkdHi4*d+_WEnG^)3~9*_4j)? zc|N1K7U_{_nM@HF-}&%QPzEpOayw}7*D>Bovy=1)CChgxRW134j5P@oZ)C)E8-z(r z*UXY?64aR)s}Vml9c^GW>#CoUw0=@t(ts&`ansIqh?AaT`hq^vXf%!u55?q8biOve z8kc9DfuK`A0FYd@c_-GWk}r`^r`_yle5^k|;4y4xiHOMOHLbZY*qeLKz1rcdkp_Ak zKqb_O{PvSKDn3M^)4Mt-o;XUEbLfF;5N@WBFKH-o=)mo$X zw;=M=Dc2P@!P4ZCpi0Q-8}hQ5(Xy^ra3%LL)Y9~G`wU3a%ksXX&cKJYJSC^lu*sft z96)l&-R)@S1MzS+e0U=km+x&|XZhDB&h%Zi`Gsj$qRa(z{7BI*ndc0Nl{syGonjui zlb18{?hrR}^Lm&HqcjH|zu(g)>x^4)-Qr=y*lp+AE~b~<$9e`Wlu5HsHAq{20PuxA z|6A-~XmvKaC4yd4Z411lXbx$paaTN5L=Un;53Ur(y4TUD)DB%~RYFRr4s<&(0^gM2 zYWlBc>!dK;Mm0P4U=Sp1Uv%^&JZ9v5drPr?^jNHBfQc=%rPHBhi6{;SJJ{=v=9O&4 zAvQbM7UR|d01#^)?+2u{H-U6YZkyMvh*D6sgJk7tSin(->sOgT+N!^iy%SgZsq59b#rES6ZHg#&Ufwa1*V%RTbO3$?fOGphK|4lk6Vvz0>Y=?Yv>hW4IG zBtP9YcfaJd?mM@6+|wc+{^;U0>*uOu9V5UF=upYo!8DXV!PiQ*YF4TNOVE;alR4rE zbqHQ|EC>1S#H~l;^NWuuA9aX|y2?LCdSI%qsVy%3jIcLGFSS?B^D#4m=XuD;5-Lj{ zbP_gO>=0e_^flEBN4{hO^X4nXB`7Cdo*sMztVNw;hCxT&p%gdUiTAaFd0NJ0+*R#v z3SRzABA&oxURP_s=E45vRotS9FEF|Z*!80XK#isT0vRKT=2`t6)|E_3OV($L9;R?d z#;q)qJ@Z?jE9a(2rS`4xEB^5rIa@Hu_Bf!C!&uB^bUdMVF<$WH`8=%2$z8(b7+}W% z#;d7xI4+HUuwytp%V2@H8W28m92=plxcc)~{eVMG!HB(1Jbzeb6n3AijKke1szbx; z&`deO!no82z;HHIc&ueR!>k|?d)u8%TwzJ2)sEGJ-dnT%QF zi1`Q?nqj$JNXGr9>W9>eY~$R%H+=WR8IF4C_JItalp zu}esR^?rhhbj88EyL4rzX5I-1_;}4`iO9%!EW3==^K>|2L%CRM%Bt?6QKT<+N(&j zTk5sopJ8;c)%V{4*{$MB$`?SzLImJ$w}ZO9VPoJUCVH)<9QL|b3|gR_PoH9Cy^hb{ z*l#enGb;xiVr;3DbZeb97<}T30ctxF(ovz*gFE^dG@sdZWQMG_A%9cAIrOTki^gGf z!@78!mCEsh`xb`4?A;5W!k}gg%mqIH7B=WzDM$-yEHCRhh46onttLBs3v61nli>HG zTH(nU$1AhGM4$l-cmmbhUtiKj#-=F6PZ%oNpKFdP&~Bj}Mqgm4X7z#COoDz1q=T7c z7gt?-RU*n+@@_CLRhd-j6$fE@{Z!n#XrK!>@XQAx3rVysJXeCezB#}h^)3j zH0{q*Z2o~{sML3L3^i?fDJ{Qst<^Us3lld!-~t))=~eEDo53ZFIXpFL~jzX#gR?=#++rCE=&CpazUIgn?l!v+vX+)?3H5 zh8`%5-rY0({3eXKAd9YJsac9kk5@S$qdlRws|LfW+LbGW0o7`%Q@F~)JDwx z4k@OoAa`b7DsuneS-_?#GZBexc-1-x$^NEzYi)aR&{=(P-+r*j{(zr36|nKX;0wHn1jV z;)6OKX^F(9(sV4;*qI)cmdI*1(_{y+5oH^}TxJgSiP?1w{Y?MD!-r&EeZ@znx(0Og zYhdjK#(8x(U0;|hy7Ym!pwD%5bw{)+DQasd_b8#7lbM+6e>zEcutPPp&rXcwVqmxe zpW>47qaJd^G@Tj0F$964Du#pz#Ic~qwBH?Dg{`Ss(}o4Cs5uhdyf||l=|RwSRrfq0M|Txc|=B9$m9rSI2Gs%-W0g3e&3nSq7xWCH;f zYkxMix=&*z`?w(}f4f8d?b7<)HO?&7E$pe?$O$F;{D z{!n2p4U`$;4G|ptHRc}%?7jck89+?A+&u?h^qOXW?hvuC>k^$mc{@NZP%tpu1-%er;HgVSGVz`en-V!De?Z3iCA*up;c1KyXLK^t9sb}Y^Pt^3N;6pItT$a0-C&A@8dsJ6*=kd&<*go_m6=1?jrSa zf)6~Rq(OC*T^cB0a!|0UxG=_Fv!F9OyH<=X)UEaL-PSbNBLZIkO_wozs=v#m;w}7J zw+Qfd#u0Gl7%WHYaNw=xi_bVLe0YMm( z6vRZb+EziAf9!W)YZ9({&IlGH8LR?enDn)b$~DFOs^GlVY%n>!l2K0!ho@Z(F?dXFS@+A=47#}{#nEmJvnT9L!o zPFX<$hONSQ41B9(4W~IUfr-rxG-kvmQQCD3BtCynWiVMn>?YBOwP`0=OK?Jw6?WPg zc*M6In~*#u#jCSP6JhiUt-zNh@)m3!rWJaOWcZ4aS0IMvj8l(sLB?=yHOegGm{&Jz4PqAj=h@MIwV4AbYUS51A8C45 zk5V(u+m@820QEEXd1!9pP-Gr9?E#11R}kCLw|5Z$(jADI{V0Y}O?n2MxGO;Z5w2{Ny;73&~in4t&h^58RgHQMX0%f$D^)pFcCeb{e1o@2rCU(Fz0{I zG1U34&tiVgre>DWDM*X}U$+I2tPbX$cam3-zRz(Qy9O84Te^_f0pp4z7Tdmy4W*Ga zkN-nlX{g#Lfz+?DJHJMUhouO`Sc;LGF4?Ad??}6{(2SE1mS!2;ze2Lnu4Pn8&+Q}; z>jqEv0pNlRHU>>?FmPmg6aHyNI}4aL)dBy@`cj%tE#Ft~r%SJ41Md{1gorific-}D zxzE3JjzbOvVBY$52p57Uz@NYEEQpw!UWry_MYH8zqU}Lr0{w@_A=|jXq+PjF#FD24 zoWT$iFsE{3#JCq_u@vHW^uB5-hBnx&OSXEheKoONA1&Bu*hD2HpU@7*^t?c11qyJP zJcN<7v{b|-Zz^$PPHGvtnDI27y-M^@BTIh(sFvw(l(0-p_>J=It$$2Q? zQ9=?(xPAa?ZGcK+nJKpI>sem0qxI->77GLD;5j_8tbyZPmH3Yg8jSAFusR^srUwkh zb5+N5)ilN>B^zyF{dkdaz_eIK;VBb^edCznK|irsxYy z{t2?-XkDeBSAg@Fm;{m!vYxeH{Kg2`~d}$WQm#m=g0;VHT%Q zn!Q@e&k+3D?-rXKl|o}lIc$bIbNLo4YGFligA7`2p^h1Ox{{6`cVJVrW#0AhDQY(O z(9b&n_hMrMPM&YAEEGMh+MFiM0kcp-?N#<9ET#g=B@sOF8#D!%obh%!+b%xpXbcw~ z1`pgVW&H5T(y8X%ri2!9EAVdKCBpNSxQMLZ7^gTd@Y-VIHSb-v`Gc%51vbId69Ny@Nkh`;IUYZk%&-%Hg z*cZ$Ekwr}hpyv?~JxM{=wGWRl$+*9OR={<=eG9A2Sc_eyy%h|dfOr$ZK1b2>h#B?Z zTm1qrirq%`1(7!%zy1yI>I#P2oMRZfxvO^kBKWhehL@j^co7d;@p%wKa%Tv~LIA>S zc&$2B-+FMAPT|>L-(QhAuYW}4>dhFP*D!!Uwt>Q9t!lc?wtc88cDRu-at{yAi4p8# zO_E+uoeX+2IPr>_qKHEN#eZzRfNFbCE86X8_PY^0!3wxz>%%E@~Uw1 zTGO9Aa18rn+8O3DV_@qL<-4HtR8MZJ>4~Kn&!{Q1yw*AF>g$!pf zt+-44rwbK2i|rWkE#d7~IRJC8Vs+7=Rj0(xdd+7o6f>11$DCc&i;9!xTf_iMZSAqQ z0SH?Vcck{&m_tyG`6Zj*J~p&1&f++VKDBlx-l1obWj&|vOS+75Q>t~(wfJRhXNSa! zfkR$a> zJ7qq7DHPAav?g1AS9v@*Zu=Up^f$ruf|f}|y1_6ReSL_Va?hk8 zth0-B?mGu43zXLtAApVRHIhcjH~-}TS}bH{NnfnIMFm;OF-#nGBJY3;c$`>B8%iNF&x&tuR~ySg?ksQxJf8zwPvZ~O`)QR zh1EN%FIMYk&*8BXcrF^3Y$X%;$dSGw>Y|6l`WwYp1WmuLRIN}eO)m$iMD-14;Nxnf zzEsZP&^%QSY(GbEN#FWA-&bKMZl+amvV4ifrr&|i#tE)D(ZbiupQpbuIZ$?F<(CW0 ziIfl3|6Qx@)8kNe!^8|d(iJ<7{M#_P3_iN5B6V;q5VJ9_cIyCIC1Hy%B@kuw0I|$H zD5nqGGNM%5X7BAMkVNxjqb1FfNn~Cz=Fi#SbFgh#YvV0S{f*--ZN-$5_N9TFK}`5~gn-F33X5q8x2c#S_>MZer}I4@imYL^;)nr3bM74OjkL-%B!50@frI;SFg)V9 z-DSA$ps|6CXZkBX($)BEkCb!u9JbYs@!2MG)+uUhk$4(X$A(`6K|v#W5S^L_9V@vP z(iS{>!6iK~$O5{)tc_tL_#p-0i8*XXNWUoLY3qWt;<{GS9rI@_6c5LN#zsUA)~8cz zZ5Cd}h@JiPH?HEj)8#lBybaUp)VO@e7Q$#LSdi)CfTlW6;a4?+hJk4C(4?kO_tP~K zUOJ3>HiispT`YzSbEIOB-Y}C;cWFED{ZQ`HWdZR`q6#$asN84TpA16xeJ3_Mv&Pa* z?T~%%*GCfk%ncPmg!~1&2C^dFJNw&Qi{eHaAcxvBbS&Cwl=LT*Ra`F-{VF|WiJT56 z8F9_3%M{x6GjR7@qkLil_y8pE=9RmezEkkF<1_VFS2_&hh}Hnrc(ig;)0P#@#g-xL z1-}kZF8aysWSc?gM@+Jf_E34KK{7sm(e1#b)B)+5wb`-SP9iXN9FUs0AW5uAuvehJ z(6=C(_qRCWWA)5k4wzb~Wpo#*jdHgW>>jTWCe1*Hd+rW9pq<}mj8{MgkC%)P5OAV(!y*<8JX)q$Vp+A<_b&rxVIiO{ev?~T%;R$5s{zdD zp8}hoD<=%{(s%=Fy1|SgvfVy)-wkEDm1aNdAu~Aj-`(O+;aKM#DE#-?Biaq|Kv@n0 zkErk>5qU!1SZPHk5mBX_ktmF2@-1t2Sb^lm@+rqj?Sn$r;hOwk^DR&ZmFlZS_FQp3 zA_yJnjn~XxB)}FUwnF`VO|^<;bxLL|X}T<}39F}72+n9Sk0qE#$0u-2>HVqqzSd9c z^?q*0ppcFWx>0lFKu`MzT zlIkkbgZQtX@wC$Fa2VK8F{s0etM2cq(ZH%|!*KU)h5<^+aB567&TLpI2-i;BaiN2g}d73WvEyzyLikixM22Kq}XYBWc-%Z99 z9^`<4S)gL!IH7i#%{ECnY1MSJUz+kXgi}$;t{St$1z3T28omsLFjQf9`?JiMa8*?V zH4?E!Je-l$2f#8LgQYUqJm*bTI%63mRfGZ)o@?`k*t*?s#mnadkVAAtVdLQp5if7u z&yRwNR*5ju)DTk&tC~;2S15s#B}Qu~^NWF*#G{lA*1Vg|{4cvh*rhw8EWvhKUxA2$ z6?xgjxWZIHy2(Nx<1?>+Q)jpl|;X&=}oCMP?kHI>XO#^^lF%ihZ^l z`j+M-fgK5=(SlF2b$_Yun{PD^O$xoO_4;iBGe*;HAvd3GB z*Lx*a15K>FKBKU#`P-b{F$W0nKT4YGNy@s447^GFZhUl!;9 z2wKZ21!i!tuk?nrF}!a5S|-+(wJzfx7}iA>#fZIOHAFsjwZPeBlkYZ_?^hiMYXMA8 zrt}<;M5__YEEpBPy9Xo#m&{ojP=NKDg4@Uv>HDBpv=z(@7j>tbZezM!DXqy(GLoCy zccKU2Tvjoz;pj9}1;?ImmMd*iCFuLEQl--uK12SE86H$pRqZe}=Ki}Dylg9c=L>xm zFo}(?UnNXKYrrcLjLTXmIlzf{r_L5={Y3vC#jr7j2UL@!2E)CH;#szWh&kFdZqZI5KMRHO%Rop} ziJicwj2r&OnaOVx!b!tur)QdjD-1P*+BOu&)y*PXADxgbqrquuU{DpDvB`7HF)Eak zS#+LiAwRF0E(N2m@Z;tmoop9Ac2(YWp9$eZX6(Q|gwLJnzgIoHv+Pq#w&B5vRmY?I zHLM_bVW6iLXRvqBIgp{km+Tk+nhKx#U6_64Zi>07^3%`}5QjrXo5UiSN7?+WJ$|Mz zz=nGWd zfb@CnMUzhbs2Ua0$dq=eGyqe-xS%++ywhH}3JJrIupPPzz>MLNU+HrT1%HMsZ_x8} zLP}a;b<6XHFQjq({0*ciTVeE@@rJp^=QYRkkaZBbP9GudGE50QO&&aBW*5_r89R8m zk-!}lUEiWTV!2BD*QGoQ0(PTz+p~l&bRVTbwq)8L4mBPM#w(L%PM@)7%NTm@iG$mg zp;Z0_LjhRnrrId!sruj6sEGuHhjIxJp86x|yrhk?e z&ERjYbfg(=;UUC&na3f=4~04$KyGz2NWRP;77)LAf!F9>=)c!E5*oYaNA9!aXAP=N ze)9hn9j~w-z<73es5Dkm$~=-)Kb*FLpjn`9mEB{`P9IOq<|&vMJ%uvQk5{h&9?l}R zXX$@q3eAn2IkZdd4y1aV17a0&=Vps)V~^Dy3q{IM{TTG=^T;~$_c%~7)lTpwiU`{t zsi^?cZ*phK_JMa(=63YtAvuQb?J!g#0(I_F&1mxapYPGmLh`&HIe*co+!B<+(3Wt+ zQ({4~0^n6?XEpJg)ldVVhj(q9NU60XH6bh!QS4%$H>wxgQx5ZUNvVn>_{P3 zdj+hK=?5Z2oKTMX@%Y|PP&z~SCcM)^2N#@MUL#z> zQy(J737}NpwjPn3>TQ~l6w^DZ-DO3-TWRLABN{k2&xUwwrPke8xASJ0n# zO>j*@KOCOekg%Nj-|t<<%=oK&h&s7&SM>J0sQpZLqzk^?Fz2$sA~1rj*$fXEhU@>S zKMwx6q)3EO+2@AR6^=q))-*gkFE5)9d66)@s9|PNOxIk%xdvY$eQkKbjgA-wCWIG8 zB9fgeIHE|`nKSw~U0gU+_Ou^bTyJ=o83Q@v{gFjdPA^$W0o@Xs);mT9Rp)Z;%ZSYp zOe)N{mMgQbpvLqgYS^&Iv;{xW$@X*l)Zf!r=XYdRCWFKDLM&~8%)czeC>vrkg+~;u zHA~9R2-@_`-j@}>*+eHfy-Rfy^KkY@d`6>t3n{!N1&t9j@!R666~-&tZVH(aoN4z| z70+8tl9bVJQgbg9vh(Z6wHYbIdRt7lv?uA*bbp_RxzS2D z2^$q@MMDiVc3GG`iNaUoi-)N37$q*d>vWQIo>^W#KW*lC_wDfU_H%dqZTGyq&@j>V zP5ozLM?XgK!#n7=FDxg-;m^DJ3t>5M#OG)z%7p4A#E=&BR#Ka=`asPY_s%%58a-eAOGm^ zrkZq1!*mCfmLBy?-q|kRg5wkG)`G3b4E=|E-tSGx3p#%FK9+GWZ=DlIKT z(Tl|(ERks9OEK8?0k|jnSouGZsa{~tL{L6U%g26J5&p08|1K7$wx&$~>{a$Ue;qkQv}Ek=V3eyAcS8N~3J~ z`m*u!_8aIFjL|SrSQLK#F(ty=Jx=K3jFTS?XB0Kz0ZJ&ym+6bKpKA53Ca0KR^rRBW zi&@gX;s~wGDO|9|tiAk++@}4Ka|ApxI&-QW(WDu-vV9) zvE*!rXOI6d!}jF~Xud1~NZlNFCtC#Us^2UDF(y27Kcdg;=VF2|76Hi;;g?G0^H!Q3 z{r=W4La+tV=apW&=!)fS%Wx~5*SFUbR_5nu3^4JjCJtKt@T#6JFnA-y9ixyL9o zcdsQS)&@Ri(wJHIvBGQ0Yqek?<8e$M86@Iq9nArsTom#aOTY8XV^@;C0K|%AV=P3_VkbgPcSZ#QRJL;oT%i{|SOKMq*pDvC~YKK5el@YIG-Ux*UbEYy$`|`yTT;hP#v*~*+ zh6CgG5*2Z3Y^n(7)CsYshNF#Cv|afZ8m$A)A8^diV#|{B2KiJmr{i1H{xYjgTL}s+gp0Y zMY{uEQyRjFP1Pzy4bDJc5i0pLQ$VSm#ujw9P8Kb1W+F`=n z{dDk0yZGpIxLlnIPd$wlJ+=06)mpN<>EwFEq1=QhB#G!j$3#`vj7+j}r}neo!O|GC%JZbDFe<>TpWT6YM@WS}>n;7UP@O871w_fU z^Xrwnd16M^HLkDlhk({kwabZ8=)gxGe7|A`uaIjap=Fm}6OiAHBlQ&=8qTO)Jl0Jc zR8)?0duYgvJHAI>>i_um%-hzx;bc3}ADF&O zm=(ewSf=T0jFJiF6teEgw^Oyk2q;-&jdmr0=y-OqW>OQ^WE4xcLR}-rOl-d`IK^t0 z=jzHvyJjQnAHxjQ^5MTd)5}!#B+)OMP(xt2;nD`c9T*c#K(d)Q+84A?XjFhK-pra- z3KGWIT6mRYS(vulI!a8&#n{$!lJyMa%reT!*ZRW#Ub(m38i^yW3;j2Dz(^Of3a+gibNpkVidQV+V=cBX&zK9sA$h`UzL zH)f}Pae3CQdQI%8VvN|zplwT;f>pY&cPfKyYgA6P2E#;n?8NfphAl9|UU;?Ru7U#f zRJ-)w`uehY`$XL1-`t;HK8$ss3kw?2;9w62~ z3p>tzg3A0C(qK$H?4n91P+ zDrlx(wvhvicG~*iAG4`voHFtp)b|D{FWX-(JUVud-@@%<;s|S1#jjd-4PvuV4??No zHYc*Xo65Y;W0E90#8n;m-QzTQi0u46&fiGXHLVp@$nv&m%?8(2to4R-enknGebtM^ zbq3Ip;CwEYeDNet)AM#Dnz8J^;V3>;%I@|2vE{&;C3(CzFf~yWNI|=vF;GzcHSk5q znuO_kHN8@NhIzd4`skZ133Ts5&irUy?Z+7O*2WM1_cN6E812qrp{}hK7?QD{gB071 z(2eL&>OjT_B|PHo;N2^nnct5Xe=p)KN_*CbG8a7eW=>&)%pvE3lB##p9`Fe@bFQgh zc{4_4OUe2-=@Sc5i<*KjzA+}A0h_1j=yuu(u+a9=`vPC%h$YCr=)J5;`asCt>cMjI z4sfJEsUo@Pvb%O*2E3rDl_WynYc8ZI&jmpZ!Y(6U%acM+m{1Ir3}9H5ZWQp(6+jnD zL58P6?IJNgd@T?)Nna=hG!<`Y1Fi0*uYXO;Sct>9&g!H!;j3#c?HKl=2Ac?2uEtV3 z;%Sln-hZ;6FGL2R&$N#Jyu{|CgjCcua|>KS@w7RDkE{ z6B~NZgXS(e*}8DX#z=Z=WYP~Wu_E-FxKu?v`-2!&jFhbaVUTT}PXs#5&qJLU=`=|D zy=JAq_KIQenKt?KL}>YqhRwrX$gS^_e$;xA-@bVMC}MEI=0!t8{o?h96bO2M0#Fs8-jXDpAxbE zBX6c8TR^`eaV$KzrdR zTG=C6FuUcC2GUr(GP`RyA$fT_cr&dZ_Crd@sdrzcE{CTXh`Xc7T(N&_Dt>m)^6M1I zq9XG_ev4GeRSe_7#qj$HkhZ?5^a^^xRU`9hGM6vu?BS37*th=XSLR1cKsLzLi6Jvr09)f!PzPF46a=F^ z%xn4xQfyF9thrPQa{X33QlYrW<{~p^LxKW}P>hVynn-Qm=*X|=g=a5J26+dr*bD4G z+iG&qgWs4lCwW052o$!2fR=#j7U_gO(|9cyCG*Frb{8I*AIuJO-`HLI$#vU*|K)Wt z-=>!hULe&fIqvptUap?W{P-VrLFasIH`V7EjQCH~2lUSo|AgOjH#JuI4|R|DOmH*X_z9{8ypWh+r3~omQ zFyc*nbUe72$^l%eI^9)!tEWy5bWl|1*5@N)6puYlEZtohji&GwSYK&!zb9f$QDjKl zDFcg@Z8!rm!qIyUC&EZilKNZJOLt#55fF@~e^*u3TUHNAup~=S>K7=^X+k`HZ-Nzc zeWDE-BlY|YK~aG^#jR-;Nq&GG=pwh-BRAd)jUOE#h+31fa9E~A^K_LKIz5*jnH~8B zeiJhEftHO0z2M9h<~tn_h36Bo@vwAAEq@Cv@zM2;^4hOU>XzI)5r-if>NmYzBSHTm z@d76k<({Y=R*E$ChsP>6m(VHiy>aFh{(n-k9)iY4?w=nP>{HRAe&SSoLK-SM**iEh znbiAgSj^8qF6M`v!Y7Vu*yY#PaN0-CbIPvrs;>duEP(@*D9s5iWYd&N zJD|JGpH0?MP+!;1{$5)j%GHfcl_R(rX3txR{Gg@;qpk{7&4kjbw(ECBW?((&f>&KhtVmiOB;)J=I5w z_{R!VQZ-elr8(}Un?m_hW9`Ei<@u^04g9Y;a5)77Xg4v0qC~Cdr+f})@xuedYv5wG zx5azve0qis2IxP;YTOL@yoj|gh4RW8F(yxCS>xdx)}({qC0=NLLMWt;Z_f%jl8ESX z_#?i;HFaXT)xFVq&Z3%RoX1|KLZW)~&u(nw->`RgX|4b8!K6Ag;zu^8s@NmV&MtC% zoxR{W7J^lOfqJj@;8eqh^r|Sy<@`@jx&Pi09GTrY&wT#J4lV!y^1s!9vx}#V=|49F zYuR$ntK4W|mpY9ffyHwdz1PiIMMLRz1m0&E+}AN#6F8(K@FqW|Z^)V+mzV%SXvdV) zoXe;E`e@OrLXg)F@C8pK?>DE;XfQ&aDe&nz@(-Kma^N{(tZ2vm$9pet3zIM360qoF zHR)CScs;kD_Lda^WoycEhLB>xquxxh(tpXpr1az3ttB00H;7Wx zpUVlG&iRfBV#T@P*Wk+@z+f^W)iZgB2T-FLQ98F$Z0fAb(Y>zdr8h6pJHk-vJ}CXB{Rm`Et=eJSmPN6`GJ;ClE*Aw}Ll z<5cWRP3jnpVn@wLhrEsChVA{9foR zmxdKPcu0!&Q?GOIRmf^z0W((~Dei;e%bl$OoR)6#&%alQPaU5dG zSIT=(GU~P&z!h(JTata)h?9MIo8t3| z@p*-0A5J{7h$D-i!I#P)}<$>!oI#3ckM7l4cP3au8rdtccim5=hb5RjV9^A*9ucbxb_zhA-nTmdV?{CRB zNlrl@)Th5)vk6-rF(&c@&(c4Q!#KJ)nbWR|1AAkt5fIFLjHah!%A@IHOMiW~{?E2q z{#taxB}4YV8{VeSNznZfv!A zx{UA^J#;z=lfPz~CqjZ^O#gmmLon#B^e7pv8=fhm!x_GblyVu+O8iZ`l#wFD`~#ux z)wE8#PB%@vEEL-n)JWlA^r z%hy4k^Dlf|f9v^i#%z>^TnIEFetXqG|8UKZ86%&dd0f7NbzinZ)t%uI`j5ThD!?S8~=xNARW*)z0Rq0$>s0zkx8%Sj}BkF2_3H&pdB z`;X@KmuD+FGy`&uz!>*yd6qTtF%r9F@6Y6M%?Httj+iG1vQLnxnG4p|X$6jvhPKE| zK-rYiaLCVdpcKUovLKaphM7`R^i~XYv#Mk0SZAP`bG);Y+hY-hWrle1 z^m)WkWEENDaG1;(JE*0pjyp(uGc?f1ZeXHA=G=K=rj`@k&38lcwS$+y#GzlH5kVmz zvlSC_(yY7vskR|!^387sn4n-juGQ49rz2J9{KsPjDQZFW%<~%XdA$AnyKzKjgzo%9 z5_Z5LdAm_VgH}{u=$D@#=+7f@IP4P-i|z^mj+?RtFtJ(wNp-yTn{8X{ulZGY9FEe? zgf31<;RY>Mv8)$<`21@vsKLVoT*g;`JxK)I$gJ&BlHYPT{G6?*!7wyj-~!scWZ-rU zLDwxaz@e8I^@JTZ?btM^Po`fGc94HcQ35$nBGQBK0$FKcA6aRO@?wFg7KNgp6bJAy zHrkkB9E_nCYz$?e7$D8Ro_})CivMev*W`Kjw!UO2dV>-PxUFi0Fy6vAmJ~L|&~6NH z*Y}e{@IPr7q|=h2u>Tlps)}-9s`^y~@86Fqq!8a?fxC{9q1XRlAu1FF{!_Gnzvv(G zp#0w=9vE-K7JkNhl#Dv!l}HAMOA~_rOSXTp{NpwT*w^{r($A#kKA;t!a=!S!YAGBN zy!12atw_GD_$0MQ^5Vyp>+G8$`eSbEjt=MD_V$aZ*dqi-c+wZ~NSwD+ZtP{~kSbyc zcI({Y$a;B_3%io+C4)#WOPS^}6Ac$V=eeFa$$E{hO6{jP zx+?9ZmBPtT*0{#mgB}UCeG6U5@ZB6YvDaZk1lG7%xxkHJ9%F}Ndv=A9C#wtNVIJmO zeEn&N?}|-=9d;=1iYeyH3FGov!lDi+5!9ySuxSf317_zUd*M$%YumaNz7~aX_Di4J zt8#(Sagcj_Lu7te7E5ZLN7<+1z{jpt76Vte`siJeyZV7^_*xuBZC^$*s$k_o-7k#@ zr&&e&B%ienj#?layQ9VqUE7H3QzYHSd5XqvrFF>4`4+3+G#pjhC&{=P4ENHp6)9`V zpR9~!jtk1E^Y6j+nOhY9PjZV@naoKd%y+6GgMUm(_c_o>=5va+q9HXIy?@X1L*?JZ zf4-!(_&1%d!Zd z@F1bBCR1pxoi^a%|DIRfgh_@Ys@HNm+-zY`7fWDgd}B=Tt$|cz+x;4UjRtG zNy3F0_ni0Tf#COs?J-&e)1PJHB7d{4M8AWFi$M#g1j3|xj0y7?G|SLcnpM@i!?}Z# zFf`b;ixxL^^*ido4Umvu%lX)!6#(QZLz1Lw17bd1J%TtLVtD##(V*dZ$2M4e*KdT! zsh10B?z!u{Cg}=?ao~`;%fR1eMO{5Ql5Xx=uGuivT+gz^Bl?E&;4dJ5c#yl_k|z~8 zpljtQ(7dJ2T(+wPfJ4y%p%IQFXx5=5YUDXNJ9)Gju+J{+2&M_wm^q{w8-qaiu@#UN zrj^6&zzZTF@nae{sG1B8e`(o9U=sRRW(?6xzyZ{xUo1Qff=D+x>v5IP z>gBYFw0_01A=Jni6rXWIW)%$+=N#eSk|t81y#pG;y3j^E6cM#(T!)Flss;xN*l0-* z;g}4*nTf$r46o)peK@E`Ez|ktN}BqqYpROx6qyLBMh@^C8cx|bZ1qJ_nUW`5)=>#% zZ9ia00h>grQjVlt%mja<=C;fcc)pG$o@V~9x&E`4kxXx{3HFtan>)cm{Jpi}(MP{N z+kZ^HbKsXaFlI3agIgD7#ufwP{y1;|NC0`9BC()gbeIAdWKb|C=(OKq1A#rtANd2{ zUCBJ^ef65CmXl0HNLIt<)O;cCX28jm1)% z*LDbJMZXHs+oB}MV_F=#RP~TI1Do^z9E}5w@Jt~2jd#U%KDZ5Nz3C%^)CAU5^-HRw0SE~nGBLP z28O-Bsd(_1DMUALl&>@w=m?PQSWP+;{(K=5(Ea;?bN8UR7X)DEgqnnG2E-x2c^WWK zWZ2pLcjK9O1_lrY&Hf{R1s_yVtT5fURFUmx?j*25Fm^&&x0C)zMKHv z2=oaggb`K1@gs0>AWtWuYeye*Mrd!VfNDn@fkrn0b#N7-pMl|iB?AM-P%FB2^wBPa z0lhUa_ru4&&^4o1mI%$=9Z=0ERVTWB)B+cwn}MOd3(4)!;y1vX6_~;p7 Date: Mon, 2 Apr 2018 14:47:18 +0200 Subject: [PATCH 091/148] 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 4f407f54..34353be8 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 092/148] 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 ac51f983..faa39a35 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 093/148] 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 0f5f446a..caa49034 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -664,6 +664,10 @@ class Html } 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 6122924f..2c496081 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -353,5 +353,17 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $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 094/148] 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 c73ffa06..f2637ac9 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 095/148] 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 d8a10b57..3f34968d 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 096/148] 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 faa39a35..f0fc6266 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 097/148] 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 d0b39ce1..e1d0937f 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 0bda3faf..88caeaeb 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 00000000..91dedc3d --- /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 f64886cf..48a84ff2 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 @@ abstract class AbstractPart 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 @@ abstract class AbstractPart 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 feb028da..b622c78b 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 @@ class Table extends Border 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 eb5af86d..7f49be7c 100644 --- a/src/PhpWord/Writer/Word2007/Style/Table.php +++ b/src/PhpWord/Writer/Word2007/Style/Table.php @@ -79,6 +79,7 @@ class Table extends AbstractStyle $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 @@ class Table extends AbstractStyle { $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 9bb6d3bd..d64079fa 100644 --- a/tests/PhpWord/Reader/Word2007/StyleTest.php +++ b/tests/PhpWord/Reader/Word2007/StyleTest.php @@ -126,4 +126,23 @@ class StyleTest extends AbstractTestReader $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 332d31aa..91fc3550 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 @@ class TableTest extends \PHPUnit\Framework\TestCase $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 @@ class TableTest extends \PHPUnit\Framework\TestCase $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 364a34d6..ec3b2483 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 @@ class TableTest extends \PHPUnit\Framework\TestCase $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 @@ class TableTest extends \PHPUnit\Framework\TestCase $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 098/148] 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 d0b39ce1..7dcefac2 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 0bda3faf..8cb6fa23 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 099/148] 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 8f33b503..dd398e46 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 100/148] 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 7dcefac2..fb07fcc2 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 e27e706e..7d8ee51f 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -723,10 +723,10 @@ class Html } 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 c9e4b4b1..9ec2249d 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -453,7 +453,7 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $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 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $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 101/148] 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 9ec2249d..f07b3f99 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -125,6 +125,7 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $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 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $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 979a4337..d365861a 100644 --- a/tests/PhpWord/Writer/Word2007/ElementTest.php +++ b/tests/PhpWord/Writer/Word2007/ElementTest.php @@ -256,7 +256,7 @@ class ElementTest extends \PHPUnit\Framework\TestCase { $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 c57f50ab..ccfffbfb 100644 --- a/tests/PhpWord/Writer/Word2007/Style/FontTest.php +++ b/tests/PhpWord/Writer/Word2007/Style/FontTest.php @@ -43,7 +43,7 @@ class FontTest extends \PHPUnit\Framework\TestCase $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 102/148] 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 91dedc3d..0d1a2419 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 103/148] 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 9c37dffe..4e7a5b22 100644 --- a/samples/Sample_27_Field.php +++ b/samples/Sample_27_Field.php @@ -6,15 +6,20 @@ include_once 'Sample_Header.php'; // 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 0e5e28ed..2efc6b0b 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 cf3fbd66..e79dd24a 100644 --- a/src/PhpWord/Writer/Word2007/Element/Field.php +++ b/src/PhpWord/Writer/Word2007/Element/Field.php @@ -177,6 +177,9 @@ class Field extends Text 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 d365861a..25c62ecc 100644 --- a/tests/PhpWord/Writer/Word2007/ElementTest.php +++ b/tests/PhpWord/Writer/Word2007/ElementTest.php @@ -288,6 +288,7 @@ class ElementTest extends \PHPUnit\Framework\TestCase $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 104/148] 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 fb07fcc2..7a49f25e 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 10c4db69..16102119 100644 --- a/src/PhpWord/Element/Table.php +++ b/src/PhpWord/Element/Table.php @@ -149,4 +149,28 @@ class Table extends AbstractElement 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 feb028da..5d4a0150 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 @@ class Table extends Border 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 8a21ee1b..088330ae 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 @@ class Table extends AbstractElement } $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 a50eea7b..b705bb5e 100644 --- a/src/PhpWord/Writer/ODText/Part/Content.php +++ b/src/PhpWord/Writer/ODText/Part/Content.php @@ -246,6 +246,7 @@ class Content extends AbstractPart $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 249321cf..f5a3c431 100644 --- a/src/PhpWord/Writer/ODText/Style/Table.php +++ b/src/PhpWord/Writer/ODText/Style/Table.php @@ -45,5 +45,18 @@ class Table extends AbstractStyle $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 25a48ab2..c365b028 100644 --- a/src/PhpWord/Writer/Word2007/Element/Table.php +++ b/src/PhpWord/Writer/Word2007/Element/Table.php @@ -76,21 +76,7 @@ class Table extends AbstractElement */ 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 105/148] 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 12728526..06feddaa 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 106/148] 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 d8763805..e1823c43 100644 --- a/samples/Sample_26_Html.php +++ b/samples/Sample_26_Html.php @@ -11,7 +11,7 @@ $html = '

              Adding element via HTML

              '; $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 7d8ee51f..cbdcecd5 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -721,7 +721,7 @@ class Html 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 f07b3f99..b61418e0 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -458,6 +458,8 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $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 107/148] 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 281c2630..52fa9580 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 06feddaa..00000000 --- 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 108/148] 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 8b5d7767..fdb2b22b 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 87d6f3e3..c24a6f8e 100644 --- a/samples/Sample_32_Chart.php +++ b/samples/Sample_32_Chart.php @@ -16,8 +16,8 @@ $section = $phpWord->addSection(); $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 755f45e1..92152c87 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 @@ class Chart extends AbstractElement */ 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 @@ class Chart extends AbstractElement * * @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 041736be..5b02e636 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 @@ class Chart extends AbstractStyle } /** + * 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 @@ class Chart extends AbstractStyle } /** + * 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 @@ class Chart extends AbstractStyle } /** + * 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 2aeccca0..17c1fd54 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 @@ class Chart extends AbstractPart } 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 @@ class Chart extends AbstractPart // 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 @@ class Chart extends AbstractPart 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 @@ class Chart extends AbstractPart $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 @@ class Chart extends AbstractPart } 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 @@ class Chart extends AbstractPart $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 @@ class Chart extends AbstractPart $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 @@ class Chart extends AbstractPart $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 00000000..9929a8f5 --- /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 109/148] Coveralls integration --- .travis.yml | 6 +++--- composer.json | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 52fa9580..d79a7dce 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 742e4bc8..e4d5927e 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 110/148] 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 48a84ff2..6cdf2b3a 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -588,6 +588,8 @@ abstract class AbstractPart return $possibleAttribute; } } + + return null; } return $attributes; diff --git a/src/PhpWord/Reader/Word2007/Settings.php b/src/PhpWord/Reader/Word2007/Settings.php index 5cfe5453..dbf34623 100644 --- a/src/PhpWord/Reader/Word2007/Settings.php +++ b/src/PhpWord/Reader/Word2007/Settings.php @@ -109,7 +109,9 @@ class Settings extends AbstractPart $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 111/148] 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 d79a7dce..bd85b2d7 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 e4d5927e..c29e901a 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 112/148] disable external code coverage --- .scrutinizer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.scrutinizer.yml b/.scrutinizer.yml index 291a6d60..2b395afd 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 113/148] update changelog [ci skip] --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b5d7767..69f0c811 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 114/148] 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 59fc3c44..7531a6bc 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 115/148] 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 e845362c..81253d0a 100644 --- a/samples/Sample_07_TemplateCloneRow.php +++ b/samples/Sample_07_TemplateCloneRow.php @@ -56,7 +56,7 @@ $templateProcessor->setValue('userPhone#3', '+1 428 889 775'); 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 2b7e9f68..ed986618 100644 --- a/samples/Sample_23_TemplateBlock.php +++ b/samples/Sample_23_TemplateBlock.php @@ -14,7 +14,7 @@ $templateProcessor->deleteBlock('DELETEME'); 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 116/148] 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 cbdcecd5..b308ec3e 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -22,6 +22,7 @@ use PhpOffice\PhpWord\Element\Row; 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 @@ class Html '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 @@ class Html * * @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 @@ class Html 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 b61418e0..63295d62 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -115,6 +115,20 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $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 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $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 117/148] 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 5593298b..ea982218 100644 --- a/samples/resources/Sample_30_ReadHTML.html +++ b/samples/resources/Sample_30_ReadHTML.html @@ -11,5 +11,11 @@
              • 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 63295d62..9b5def85 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -485,10 +485,10 @@ class HtmlTest extends \PHPUnit\Framework\TestCase { $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 118/148] fixes --- src/PhpWord/Shared/Html.php | 66 +++++++++++++++---------------- tests/PhpWord/Shared/HtmlTest.php | 8 ++-- 2 files changed, 38 insertions(+), 36 deletions(-) diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index b308ec3e..24f695c7 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -20,9 +20,9 @@ namespace PhpOffice\PhpWord\Shared; 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 @@ class Html * * @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 @@ class Html break; } } - if( strpos( $src, "data:image" ) !== false ){ - if( ! is_dir( self::$imgdir ) ) - mkdir( self::$imgdir ) ; + if (strpos($src, 'data:image') !== false) { + if (!is_dir(self::$imgdir)) { + mkdir(self::$imgdir); + } - $match = array(); - preg_match( '/data:image\/(\w+);base64,(.+)/', $src, $match ); + $match = array(); + preg_match('/data:image\/(\w+);base64,(.+)/', $src, $match); - $src = $imgFile = self::$imgdir . uniqid() . "." . $match[1]; + $src = $imgFile = self::$imgdir . uniqid() . '.' . $match[1]; - $ifp = fopen( $imgFile, "wb"); + $ifp = fopen($imgFile, 'wb'); - fwrite($ifp, base64_decode( $match[2] ) ); - fclose($ifp); + fwrite($ifp, base64_decode($match[2])); + fclose($ifp); + } + $src = urldecode($src); - } - $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 ); - } + && 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]; + 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"); + $ifp = fopen($src, 'wb'); - fwrite($ifp, $imgBlob ); - fclose($ifp); - } - } + 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 9b5def85..8c42544d 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -115,6 +115,7 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $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 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $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 @@ class HtmlTest extends \PHPUnit\Framework\TestCase { $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 119/148] 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 24f695c7..97b27018 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -656,14 +656,12 @@ class Html } } 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 @@ class Html 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 8c42544d..6925e3c2 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -480,6 +480,22 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $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 120/148] 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 ea982218..b3d2fad2 100644 --- a/samples/resources/Sample_30_ReadHTML.html +++ b/samples/resources/Sample_30_ReadHTML.html @@ -12,10 +12,14 @@

              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 97b27018..23172769 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -655,6 +655,7 @@ class Html break; } } + $origin_src= $src; if (strpos($src, 'data:image') !== false) { $tmpDir = Settings::getTempDir() . '/'; @@ -678,7 +679,7 @@ class Html } 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 @@ class Html 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 6925e3c2..481b5d75 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -519,6 +519,20 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $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 121/148] 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 23172769..58ce2412 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -655,7 +655,7 @@ class Html break; } } - $origin_src= $src; + $originSrc = $src; if (strpos($src, 'data:image') !== false) { $tmpDir = Settings::getTempDir() . '/'; @@ -692,10 +692,10 @@ class Html } } - 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 122/148] add .gitattributes --- .gitattributes | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..f3d033a7 --- /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 123/148] 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 481b5d75..32f4bf46 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -521,11 +521,12 @@ class HtmlTest extends \PHPUnit\Framework\TestCase /** * 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 124/148] 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 58ce2412..239cfd1d 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -666,8 +666,10 @@ class Html $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 @@ class Html $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 125/148] 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 bd85b2d7..c72dd8c2 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 c29e901a..dd3a2de8 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 5ff85b8f..e3e54ed4 100644 --- a/src/PhpWord/Element/AbstractElement.php +++ b/src/PhpWord/Element/AbstractElement.php @@ -347,7 +347,7 @@ abstract class AbstractElement * * @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 b5cc0c51..a78df2c4 100644 --- a/src/PhpWord/PhpWord.php +++ b/src/PhpWord/PhpWord.php @@ -35,10 +35,10 @@ use PhpOffice\PhpWord\Exception\Exception; * @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 47242621..62783b63 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 @@ class Style * 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 @@ class Style * 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 @@ class Style * 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 @@ class Style /** * 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 @@ class Style /** * 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 c58cee49..e9f3c9d6 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 126/148] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dfcce5a4..e7b7ed68 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 127/148] 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 dfcce5a4..e7b7ed68 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 5593298b..b3d2fad2 100644 --- a/samples/resources/Sample_30_ReadHTML.html +++ b/samples/resources/Sample_30_ReadHTML.html @@ -11,5 +11,15 @@
              • 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 cbdcecd5..239cfd1d 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -20,6 +20,7 @@ namespace PhpOffice\PhpWord\Shared; 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 @@ class Html '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 @@ class Html 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 b61418e0..32f4bf46 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -116,6 +116,21 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $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 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $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 128/148] 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 4e9220fd..21c416af 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 129/148] 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 21c416af..5284bbf3 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 130/148] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bfb1cb5c..221377df 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 131/148] 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 e7b7ed68..868a4eba 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 10c4db69..16102119 100644 --- a/src/PhpWord/Element/Table.php +++ b/src/PhpWord/Element/Table.php @@ -149,4 +149,28 @@ class Table extends AbstractElement 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 b622c78b..0f7bf7dc 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 @@ class Table extends Border 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 8a21ee1b..088330ae 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 @@ class Table extends AbstractElement } $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 a50eea7b..b705bb5e 100644 --- a/src/PhpWord/Writer/ODText/Part/Content.php +++ b/src/PhpWord/Writer/ODText/Part/Content.php @@ -246,6 +246,7 @@ class Content extends AbstractPart $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 249321cf..f5a3c431 100644 --- a/src/PhpWord/Writer/ODText/Style/Table.php +++ b/src/PhpWord/Writer/ODText/Style/Table.php @@ -45,5 +45,18 @@ class Table extends AbstractStyle $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 25a48ab2..c365b028 100644 --- a/src/PhpWord/Writer/Word2007/Element/Table.php +++ b/src/PhpWord/Writer/Word2007/Element/Table.php @@ -76,21 +76,7 @@ class Table extends AbstractElement */ 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 132/148] 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 16102119..44fe3744 100644 --- a/src/PhpWord/Element/Table.php +++ b/src/PhpWord/Element/Table.php @@ -135,15 +135,14 @@ class Table extends AbstractElement 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 @@ class Table extends AbstractElement 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 b705bb5e..99ee9353 100644 --- a/src/PhpWord/Writer/ODText/Part/Content.php +++ b/src/PhpWord/Writer/ODText/Part/Content.php @@ -239,6 +239,7 @@ class Content extends AbstractPart $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 f5a3c431..5ddee25a 100644 --- a/src/PhpWord/Writer/ODText/Style/Table.php +++ b/src/PhpWord/Writer/ODText/Style/Table.php @@ -47,8 +47,9 @@ class Table extends AbstractStyle $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 133/148] 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 5a3393b3..8af44d20 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 134/148] 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 b3d2fad2..3ccbb5f2 100644 --- a/samples/resources/Sample_30_ReadHTML.html +++ b/samples/resources/Sample_30_ReadHTML.html @@ -17,9 +17,12 @@

              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 58ce2412..f5a7e567 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -530,7 +530,7 @@ class Html $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 3798a07b..fbe92c25 100644 --- a/tests/PhpWord/Shared/ConverterTest.php +++ b/tests/PhpWord/Shared/ConverterTest.php @@ -126,6 +126,7 @@ class ConverterTest extends \PHPUnit\Framework\TestCase $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 481b5d75..ac273ad0 100644 --- a/tests/PhpWord/Shared/HtmlTest.php +++ b/tests/PhpWord/Shared/HtmlTest.php @@ -141,6 +141,7 @@ class HtmlTest extends \PHPUnit\Framework\TestCase 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 @@ class HtmlTest extends \PHPUnit\Framework\TestCase $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 135/148] 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 3ccbb5f2..0ff1a414 100644 --- a/samples/resources/Sample_30_ReadHTML.html +++ b/samples/resources/Sample_30_ReadHTML.html @@ -17,12 +17,5 @@

              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 136/148] 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 dd3a2de8..9a14618e 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 137/148] 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 9a14618e..4bba86b3 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 239cfd1d..a4281678 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -71,6 +71,7 @@ class Html } // 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 72446ae7..946d6691 100644 --- a/src/PhpWord/TemplateProcessor.php +++ b/src/PhpWord/TemplateProcessor.php @@ -113,6 +113,7 @@ class TemplateProcessor */ 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 8c937bf5..81de7eff 100644 --- a/tests/PhpWord/_includes/XmlDocument.php +++ b/tests/PhpWord/_includes/XmlDocument.php @@ -76,8 +76,10 @@ class XmlDocument $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 138/148] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cdd78870..d2b009dc 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 139/148] 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 015dd2ed..17fcfa39 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 140/148] 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 d2b009dc..03387b37 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 00000000..5c80af0c --- /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 3b8690cd..cb50a31b 100644 --- a/src/PhpWord/Writer/RTF/Style/Paragraph.php +++ b/src/PhpWord/Writer/RTF/Style/Paragraph.php @@ -64,9 +64,49 @@ class Paragraph extends AbstractStyle 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 00000000..fe1f9363 --- /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 5f04f1a8..317014c6 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 @@ class StyleTest extends \PHPUnit\Framework\TestCase $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 141/148] 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 d0b39ce1..1f1e194b 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 6dc9be2c..1844e82e 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 142/148] 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 584ed83e..197f8022 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 fc0c7ecd..00000000 --- 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 42d3a5d5..b764642a 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 5a050c54..00000000 --- a/tests/PhpWord/Shared/Microsoft/PasswordEncoderTest.php +++ /dev/null @@ -1,91 +0,0 @@ - Date: Sat, 14 Jul 2018 02:54:17 +0200 Subject: [PATCH 143/148] 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 5ae6d0f2..666c63b9 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 569cea92..eb261b1f 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 a4281678..f725c366 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -75,7 +75,7 @@ class Html $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 858ecfef..6a05a34d 100644 --- a/src/PhpWord/Writer/Word2007/Element/Title.php +++ b/src/PhpWord/Writer/Word2007/Element/Title.php @@ -47,6 +47,7 @@ class Title extends AbstractElement $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 17c1fd54..5a3ef276 100644 --- a/src/PhpWord/Writer/Word2007/Part/Chart.php +++ b/src/PhpWord/Writer/Word2007/Part/Chart.php @@ -330,11 +330,11 @@ class Chart extends AbstractPart $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 90044b92..b76ddded 100644 --- a/tests/PhpWord/Writer/HTML/ElementTest.php +++ b/tests/PhpWord/Writer/HTML/ElementTest.php @@ -70,7 +70,7 @@ class ElementTest extends \PHPUnit\Framework\TestCase $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 @@ class ElementTest extends \PHPUnit\Framework\TestCase $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 @@ class ElementTest extends \PHPUnit\Framework\TestCase $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 81de7eff..7062ebbf 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 @@ class XmlDocument } 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 144/148] 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 c0c7f217..1a17b747 100644 --- a/src/PhpWord/Element/OLEObject.php +++ b/src/PhpWord/Element/OLEObject.php @@ -83,7 +83,7 @@ class OLEObject extends AbstractElement $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 1ce2dcdd..374f1a99 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 @@ class PreserveText extends AbstractElement if (isset($matches[0])) { $this->text = $matches; } - - return $this; } /** @@ -91,7 +89,7 @@ class PreserveText extends AbstractElement /** * 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 eb261b1f..d01f7f33 100644 --- a/src/PhpWord/Element/Title.php +++ b/src/PhpWord/Element/Title.php @@ -74,8 +74,6 @@ class Title extends AbstractElement 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 197f8022..15aa3ff1 100644 --- a/src/PhpWord/Metadata/Protection.php +++ b/src/PhpWord/Metadata/Protection.php @@ -113,7 +113,7 @@ class Protection /** * Set password * - * @param $password + * @param string $password * @return self */ public function setPassword($password) @@ -136,7 +136,7 @@ class Protection /** * Set count for hash iterations * - * @param $spinCount + * @param int $spinCount * @return self */ public function setSpinCount($spinCount) @@ -159,7 +159,7 @@ class Protection /** * 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 dbf34623..3084943b 100644 --- a/src/PhpWord/Reader/Word2007/Settings.php +++ b/src/PhpWord/Reader/Word2007/Settings.php @@ -81,7 +81,7 @@ class Settings extends AbstractPart * * @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 @@ class Settings extends AbstractPart * * @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 @@ class Settings extends AbstractPart * * @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 @@ class Settings extends AbstractPart * * @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 @@ class Settings extends AbstractPart * * @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 5c80af0c..dd52230e 100644 --- a/src/PhpWord/Writer/RTF/Style/Indentation.php +++ b/src/PhpWord/Writer/RTF/Style/Indentation.php @@ -33,7 +33,7 @@ class Indentation extends AbstractStyle { $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 145/148] 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 0ff1a414..b3d2fad2 100644 --- a/samples/resources/Sample_30_ReadHTML.html +++ b/samples/resources/Sample_30_ReadHTML.html @@ -17,5 +17,9 @@

              Includes images

              + + + + From 87498e43e18f31e3161256ac0f70092c86718914 Mon Sep 17 00:00:00 2001 From: troosan Date: Sat, 14 Jul 2018 17:21:30 +0200 Subject: [PATCH 146/148] 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 03387b37..56a1d9ad 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 4a50a595..d7a76f78 100644 --- a/src/PhpWord/Style/Language.php +++ b/src/PhpWord/Style/Language.php @@ -123,8 +123,7 @@ final class Language extends AbstractStyle */ public function setLatin($latin) { - $this->validateLocale($latin); - $this->latin = $latin; + $this->latin = $this->validateLocale($latin); return $this; } @@ -173,8 +172,7 @@ final class Language extends AbstractStyle */ public function setEastAsia($eastAsia) { - $this->validateLocale($eastAsia); - $this->eastAsia = $eastAsia; + $this->eastAsia = $this->validateLocale($eastAsia); return $this; } @@ -198,8 +196,7 @@ final class Language extends AbstractStyle */ public function setBidirectional($bidirectional) { - $this->validateLocale($bidirectional); - $this->bidirectional = $bidirectional; + $this->bidirectional = $this->validateLocale($bidirectional); return $this; } @@ -218,12 +215,18 @@ final class Language extends AbstractStyle * 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 99741cea..3bf516f8 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 @@ class LanguageTest extends \PHPUnit\Framework\TestCase */ 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 147/148] 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 c72dd8c2..db77ff05 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 148/148] 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 9f0e8a43..5d8a855b 100644 --- a/composer.json +++ b/composer.json @@ -90,7 +90,7 @@ }, "extra": { "branch-alias": { - "dev-develop": "0.15-dev" + "dev-develop": "0.16-dev" } } }