diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md
index 1c1557a940..d1fa6cba99 100644
--- a/docs/changes/1.x/1.4.0.md
+++ b/docs/changes/1.x/1.4.0.md
@@ -16,10 +16,16 @@
- Writer ODText: Support for images inside a textRun by [@Progi1984](https://github.com/Progi1984) fixing [#2240](https://github.com/PHPOffice/PHPWord/issues/2240) in [#2668](https://github.com/PHPOffice/PHPWord/pull/2668)
- Allow vAlign and vMerge on Style\Cell to be set to null by [@SpraxDev](https://github.com/SpraxDev) fixing [#2673](https://github.com/PHPOffice/PHPWord/issues/2673) in [#2676](https://github.com/PHPOffice/PHPWord/pull/2676)
- Reader HTML: Support for differents size units for table by [@Progi1984](https://github.com/Progi1984) fixing [#2384](https://github.com/PHPOffice/PHPWord/issues/2384), [#2701](https://github.com/PHPOffice/PHPWord/issues/2701) in [#2725](https://github.com/PHPOffice/PHPWord/pull/2725)
+- Reader Word2007 : Respect paragraph indent units by [@tugmaks](https://github.com/tugmaks) & [@Progi1984](https://github.com/Progi1984) fixing [#507](https://github.com/PHPOffice/PHPWord/issues/507) in [#2726](https://github.com/PHPOffice/PHPWord/pull/2726)
### Miscellaneous
- Bump dompdf/dompdf from 2.0.4 to 3.0.0 by [@dependabot](https://github.com/dependabot) fixing [#2621](https://github.com/PHPOffice/PHPWord/issues/2621) in [#2666](https://github.com/PHPOffice/PHPWord/pull/2666)
- Add test case to make sure vMerge defaults to 'continue' by [@SpraxDev](https://github.com/SpraxDev) in [#2677](https://github.com/PHPOffice/PHPWord/pull/2677)
+### Deprecations
+- Deprecate `PhpOffice\PhpWord\Style\Paragraph::getIndent()` : Use `PhpOffice\PhpWord\Style\Paragraph::getIndentLeft()`
+- Deprecate `PhpOffice\PhpWord\Style\Paragraph::setHanging()` : Use `PhpOffice\PhpWord\Style\Paragraph::setIndentHanging()`
+- Deprecate `PhpOffice\PhpWord\Style\Paragraph::setIndent()` : Use `PhpOffice\PhpWord\Style\Paragraph::setIndentLeft()`
+
### BC Breaks
diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php
index 12ef96d287..d14ca603e7 100644
--- a/src/PhpWord/Reader/Word2007/AbstractPart.php
+++ b/src/PhpWord/Reader/Word2007/AbstractPart.php
@@ -662,8 +662,10 @@ protected function readParagraphStyle(XMLReader $xmlReader, DOMElement $domNode)
'alignment' => [self::READ_VALUE, 'w:jc'],
'basedOn' => [self::READ_VALUE, 'w:basedOn'],
'next' => [self::READ_VALUE, 'w:next'],
- 'indent' => [self::READ_VALUE, 'w:ind', 'w:left'],
- 'hanging' => [self::READ_VALUE, 'w:ind', 'w:hanging'],
+ 'indentLeft' => [self::READ_VALUE, 'w:ind', 'w:left'],
+ 'indentRight' => [self::READ_VALUE, 'w:ind', 'w:right'],
+ 'indentHanging' => [self::READ_VALUE, 'w:ind', 'w:hanging'],
+ 'indentFirstLine' => [self::READ_VALUE, 'w:ind', 'w:firstLine'],
'spaceAfter' => [self::READ_VALUE, 'w:spacing', 'w:after'],
'spaceBefore' => [self::READ_VALUE, 'w:spacing', 'w:before'],
'widowControl' => [self::READ_FALSE, 'w:widowControl'],
diff --git a/src/PhpWord/Style/AbstractStyle.php b/src/PhpWord/Style/AbstractStyle.php
index 3d883978dd..338ae6a5ef 100644
--- a/src/PhpWord/Style/AbstractStyle.php
+++ b/src/PhpWord/Style/AbstractStyle.php
@@ -317,12 +317,11 @@ protected function setEnumVal($value = null, $enum = [], $default = null)
* Set object value.
*
* @param mixed $value
- * @param string $styleName
* @param mixed &$style
*
* @return mixed
*/
- protected function setObjectVal($value, $styleName, &$style)
+ protected function setObjectVal($value, string $styleName, &$style)
{
$styleClass = substr(static::class, 0, (int) strrpos(static::class, '\\')) . '\\' . $styleName;
if (is_array($value)) {
diff --git a/src/PhpWord/Style/Indentation.php b/src/PhpWord/Style/Indentation.php
index 22b8f44c0b..c2032dd22f 100644
--- a/src/PhpWord/Style/Indentation.php
+++ b/src/PhpWord/Style/Indentation.php
@@ -29,30 +29,30 @@ class Indentation extends AbstractStyle
/**
* Left indentation (twip).
*
- * @var float|int
+ * @var null|float
*/
private $left = 0;
/**
* Right indentation (twip).
*
- * @var float|int
+ * @var null|float
*/
private $right = 0;
/**
* Additional first line indentation (twip).
*
- * @var float|int
+ * @var null|float
*/
private $firstLine = 0;
/**
* Indentation removed from first line (twip).
*
- * @var float|int
+ * @var null|float
*/
- private $hanging;
+ private $hanging = 0;
/**
* Create a new instance.
@@ -66,96 +66,72 @@ public function __construct($style = [])
/**
* Get left.
- *
- * @return float|int
*/
- public function getLeft()
+ public function getLeft(): ?float
{
return $this->left;
}
/**
* Set left.
- *
- * @param float|int $value
- *
- * @return self
*/
- public function setLeft($value)
+ public function setLeft(?float $value): self
{
- $this->left = $this->setNumericVal($value, $this->left);
+ $this->left = $this->setNumericVal($value);
return $this;
}
/**
* Get right.
- *
- * @return float|int
*/
- public function getRight()
+ public function getRight(): ?float
{
return $this->right;
}
/**
* Set right.
- *
- * @param float|int $value
- *
- * @return self
*/
- public function setRight($value)
+ public function setRight(?float $value): self
{
- $this->right = $this->setNumericVal($value, $this->right);
+ $this->right = $this->setNumericVal($value);
return $this;
}
/**
* Get first line.
- *
- * @return float|int
*/
- public function getFirstLine()
+ public function getFirstLine(): ?float
{
return $this->firstLine;
}
/**
* Set first line.
- *
- * @param float|int $value
- *
- * @return self
*/
- public function setFirstLine($value)
+ public function setFirstLine(?float $value): self
{
- $this->firstLine = $this->setNumericVal($value, $this->firstLine);
+ $this->firstLine = $this->setNumericVal($value);
return $this;
}
/**
* Get hanging.
- *
- * @return float|int
*/
- public function getHanging()
+ public function getHanging(): ?float
{
return $this->hanging;
}
/**
* Set hanging.
- *
- * @param float|int $value
- *
- * @return self
*/
- public function setHanging($value = null)
+ public function setHanging(?float $value = null): self
{
- $this->hanging = $this->setNumericVal($value, $this->hanging);
+ $this->hanging = $this->setNumericVal($value);
return $this;
}
diff --git a/src/PhpWord/Style/Paragraph.php b/src/PhpWord/Style/Paragraph.php
index 43acedaee2..5dda985fe5 100644
--- a/src/PhpWord/Style/Paragraph.php
+++ b/src/PhpWord/Style/Paragraph.php
@@ -322,74 +322,132 @@ public function setNext($value = null)
return $this;
}
+ /**
+ * Get hanging.
+ */
+ public function getHanging(): ?float
+ {
+ return $this->getChildStyleValue($this->indentation, 'hanging');
+ }
+
/**
* Get indentation.
*
- * @return null|Indentation
+ * @deprecated 1.4.0 Use getIndentLeft
*/
- public function getIndentation()
+ public function getIndent(): ?float
+ {
+ return $this->getChildStyleValue($this->indentation, 'left');
+ }
+
+ /**
+ * Get indentation.
+ */
+ public function getIndentation(): ?Indentation
{
return $this->indentation;
}
/**
- * Set shading.
- *
- * @param mixed $value
- *
- * @return self
+ * Get firstLine.
*/
- public function setIndentation($value = null)
+ public function getIndentFirstLine(): ?float
{
- $this->setObjectVal($value, 'Indentation', $this->indentation);
+ return $this->getChildStyleValue($this->indentation, 'firstLine');
+ }
- return $this;
+ /**
+ * Get left indentation.
+ */
+ public function getIndentLeft(): ?float
+ {
+ return $this->getChildStyleValue($this->indentation, 'left');
}
/**
- * Get indentation.
+ * Get right indentation.
+ */
+ public function getIndentRight(): ?float
+ {
+ return $this->getChildStyleValue($this->indentation, 'right');
+ }
+
+ /**
+ * Set hanging.
*
- * @return int
+ * @deprecated 1.4.0 Use setIndentHanging
*/
- public function getIndent()
+ public function setHanging(?float $value = null): self
{
- return $this->getChildStyleValue($this->indentation, 'left');
+ return $this->setIndentation(['hanging' => $value]);
}
/**
* Set indentation.
*
- * @param int $value
- *
- * @return self
+ * @deprecated 1.4.0 Use setIndentLeft
*/
- public function setIndent($value = null)
+ public function setIndent(?float $value = null): self
{
return $this->setIndentation(['left' => $value]);
}
/**
- * Get hanging.
+ * Set indentation.
*
- * @return int
+ * @param array{
+ * left?:null|float|int|numeric-string,
+ * right?:null|float|int|numeric-string,
+ * hanging?:null|float|int|numeric-string,
+ * firstLine?:null|float|int|numeric-string
+ * } $value
*/
- public function getHanging()
+ public function setIndentation(array $value = []): self
{
- return $this->getChildStyleValue($this->indentation, 'hanging');
+ $value = array_map(function ($indent) {
+ if (is_string($indent) || is_numeric($indent)) {
+ $indent = $this->setFloatVal($indent);
+ }
+
+ return $indent;
+ }, $value);
+ $this->setObjectVal($value, 'Indentation', $this->indentation);
+
+ return $this;
}
/**
- * Set hanging.
- *
- * @param int $value
- *
- * @return self
+ * Set hanging indentation.
*/
- public function setHanging($value = null)
+ public function setIndentHanging(?float $value = null): self
{
return $this->setIndentation(['hanging' => $value]);
}
+ /**
+ * Set firstline indentation.
+ */
+ public function setIndentFirstLine(?float $value = null): self
+ {
+ return $this->setIndentation(['firstLine' => $value]);
+ }
+
+ /**
+ * Set left indentation.
+ */
+ public function setIndentLeft(?float $value = null): self
+ {
+ return $this->setIndentation(['left' => $value]);
+ }
+
+ /**
+ * Set right indentation.
+ */
+ public function setIndentRight(?float $value = null): self
+ {
+ return $this->setIndentation(['right' => $value]);
+ }
+
/**
* Get spacing.
*
diff --git a/tests/PhpWordTests/Reader/Word2007/StyleTest.php b/tests/PhpWordTests/Reader/Word2007/StyleTest.php
index 006e6ff01f..347c0350f9 100644
--- a/tests/PhpWordTests/Reader/Word2007/StyleTest.php
+++ b/tests/PhpWordTests/Reader/Word2007/StyleTest.php
@@ -18,6 +18,8 @@
namespace PhpOffice\PhpWordTests\Reader\Word2007;
+use Generator;
+use PhpOffice\PhpWord\Element\TextRun;
use PhpOffice\PhpWord\SimpleType\Border;
use PhpOffice\PhpWord\SimpleType\TblWidth;
use PhpOffice\PhpWord\SimpleType\VerticalJc;
@@ -221,7 +223,7 @@ public function testReadPosition(): void
$phpWord = $this->getDocumentFromString(['document' => $documentXml]);
$elements = $phpWord->getSection(0)->getElements();
- /** @var \PhpOffice\PhpWord\Element\TextRun $elements */
+ /** @var TextRun $elements */
$textRun = $elements[0];
self::assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $textRun);
self::assertInstanceOf('PhpOffice\PhpWord\Element\Text', $textRun->getElement(0));
@@ -282,7 +284,7 @@ public function testReadHidden(): void
$phpWord = $this->getDocumentFromString(['document' => $documentXml]);
$elements = $phpWord->getSection(0)->getElements();
- /** @var \PhpOffice\PhpWord\Element\TextRun $elements */
+ /** @var TextRun $elements */
$textRun = $elements[0];
self::assertInstanceOf('PhpOffice\PhpWord\Element\TextRun', $textRun);
self::assertInstanceOf('PhpOffice\PhpWord\Element\Text', $textRun->getElement(0));
@@ -328,4 +330,45 @@ public function testPageVerticalAlign(): void
$sectionStyle = $phpWord->getSection(0)->getStyle();
self::assertEquals(VerticalJc::CENTER, $sectionStyle->getVAlign());
}
+
+ /**
+ * @dataProvider providerIndentation
+ */
+ public function testIndentation(string $indent, float $left, float $right, ?float $hanging, float $firstLine): void
+ {
+ $documentXml = "
+
+ $indent
+
+
+ 1.
+
+ ";
+
+ $phpWord = $this->getDocumentFromString(['document' => $documentXml]);
+
+ $section = $phpWord->getSection(0);
+ $textRun = $section->getElements()[0];
+ self::assertInstanceOf(TextRun::class, $textRun);
+
+ $paragraphStyle = $textRun->getParagraphStyle();
+ self::assertInstanceOf(Style\Paragraph::class, $paragraphStyle);
+
+ $indentation = $paragraphStyle->getIndentation();
+ self::assertSame($left, $indentation->getLeft());
+ self::assertSame($right, $indentation->getRight());
+ self::assertSame($hanging, $indentation->getHanging());
+ self::assertSame($firstLine, $indentation->getFirstLine());
+ }
+
+ /**
+ * @return Generator
+ */
+ public static function providerIndentation()
+ {
+ yield ['', 709.00, 488.00, 10.0, 490.00];
+ yield ['', 0, 0, 10.0, 490.00];
+ yield ['', 709.00, 0, 0, 0];
+ yield ['', 0, 488.00, 0, 0];
+ }
}
diff --git a/tests/PhpWordTests/Style/ParagraphTest.php b/tests/PhpWordTests/Style/ParagraphTest.php
index f99107a93b..6a6e777cfc 100644
--- a/tests/PhpWordTests/Style/ParagraphTest.php
+++ b/tests/PhpWordTests/Style/ParagraphTest.php
@@ -144,6 +144,155 @@ public function testTabs(): void
self::assertCount(2, $object->getTabs());
}
+ public function testHanging(): void
+ {
+ $rand = mt_rand(0, 255);
+
+ $object = new Paragraph();
+ self::assertNull($object->getHanging());
+ self::assertInstanceOf(Paragraph::class, $object->setHanging($rand));
+ self::assertEquals($rand, $object->getHanging());
+ self::assertInstanceOf(Paragraph::class, $object->setHanging(null));
+ self::assertNull($object->getHanging());
+ self::assertInstanceOf(Paragraph::class, $object->setHanging($rand));
+ self::assertEquals($rand, $object->getHanging());
+ self::assertInstanceOf(Paragraph::class, $object->setHanging());
+ self::assertNull($object->getHanging());
+ }
+
+ public function testIndent(): void
+ {
+ $rand = mt_rand(0, 255);
+
+ $object = new Paragraph();
+ self::assertNull($object->getIndent());
+ self::assertInstanceOf(Paragraph::class, $object->setIndent($rand));
+ self::assertEquals($rand, $object->getIndent());
+ self::assertInstanceOf(Paragraph::class, $object->setIndent(null));
+ self::assertNull($object->getIndent());
+ self::assertInstanceOf(Paragraph::class, $object->setIndent($rand));
+ self::assertEquals($rand, $object->getIndent());
+ self::assertInstanceOf(Paragraph::class, $object->setIndent());
+ self::assertNull($object->getIndent());
+ }
+
+ public function testIndentation(): void
+ {
+ $rand = mt_rand(0, 255);
+ $rand2 = mt_rand(0, 255);
+
+ $object = new Paragraph();
+ self::assertNull($object->getIndentation());
+ // Set Basic indentation
+ self::assertInstanceOf(Paragraph::class, $object->setIndentation([]));
+ self::assertNotNull($object->getIndentation());
+ self::assertEquals(0, $object->getIndentation()->getLeft());
+ self::assertEquals(0, $object->getIndentation()->getRight());
+ self::assertEquals(0, $object->getIndentation()->getHanging());
+ self::assertEquals(0, $object->getIndentation()->getFirstLine());
+ // Set indentation : left
+ self::assertInstanceOf(Paragraph::class, $object->setIndentation([
+ 'left' => $rand,
+ ]));
+ self::assertNotNull($object->getIndentation());
+ self::assertEquals($rand, $object->getIndentation()->getLeft());
+ self::assertEquals(0, $object->getIndentation()->getRight());
+ self::assertEquals(0, $object->getIndentation()->getHanging());
+ self::assertEquals(0, $object->getIndentation()->getFirstLine());
+ // Set indentation : right
+ self::assertInstanceOf(Paragraph::class, $object->setIndentation([
+ 'right' => $rand,
+ ]));
+ self::assertNotNull($object->getIndentation());
+ self::assertEquals($rand, $object->getIndentation()->getLeft());
+ self::assertEquals($rand, $object->getIndentation()->getRight());
+ self::assertEquals(0, $object->getIndentation()->getHanging());
+ self::assertEquals(0, $object->getIndentation()->getFirstLine());
+ // Set indentation : hanging
+ self::assertInstanceOf(Paragraph::class, $object->setIndentation([
+ 'hanging' => $rand,
+ ]));
+ self::assertNotNull($object->getIndentation());
+ self::assertEquals($rand, $object->getIndentation()->getLeft());
+ self::assertEquals($rand, $object->getIndentation()->getRight());
+ self::assertEquals($rand, $object->getIndentation()->getHanging());
+ self::assertEquals(0, $object->getIndentation()->getFirstLine());
+ // Set indentation : firstline
+ self::assertInstanceOf(Paragraph::class, $object->setIndentation([
+ 'firstline' => $rand,
+ ]));
+ self::assertNotNull($object->getIndentation());
+ self::assertEquals($rand, $object->getIndentation()->getLeft());
+ self::assertEquals($rand, $object->getIndentation()->getRight());
+ self::assertEquals($rand, $object->getIndentation()->getHanging());
+ self::assertEquals($rand, $object->getIndentation()->getFirstLine());
+ // Replace indentation : left & firstline
+ self::assertInstanceOf(Paragraph::class, $object->setIndentation([
+ 'left' => $rand2,
+ 'firstline' => $rand2,
+ ]));
+ self::assertNotNull($object->getIndentation());
+ self::assertEquals($rand2, $object->getIndentation()->getLeft());
+ self::assertEquals($rand, $object->getIndentation()->getRight());
+ self::assertEquals($rand, $object->getIndentation()->getHanging());
+ self::assertEquals($rand2, $object->getIndentation()->getFirstLine());
+ // Replace indentation : N/A
+ self::assertInstanceOf(Paragraph::class, $object->setIndentation());
+ self::assertNotNull($object->getIndentation());
+ self::assertEquals($rand2, $object->getIndentation()->getLeft());
+ self::assertEquals($rand, $object->getIndentation()->getRight());
+ self::assertEquals($rand, $object->getIndentation()->getHanging());
+ self::assertEquals($rand2, $object->getIndentation()->getFirstLine());
+ }
+
+ public function testIndentFirstLine(): void
+ {
+ $rand = mt_rand(0, 255);
+
+ $object = new Paragraph();
+ self::assertNull($object->getIndentFirstLine());
+ self::assertInstanceOf(Paragraph::class, $object->setIndentFirstLine($rand));
+ self::assertEquals($rand, $object->getIndentFirstLine());
+ self::assertInstanceOf(Paragraph::class, $object->setIndentFirstLine(null));
+ self::assertNull($object->getIndentFirstLine());
+ self::assertInstanceOf(Paragraph::class, $object->setIndentFirstLine($rand));
+ self::assertEquals($rand, $object->getIndentFirstLine());
+ self::assertInstanceOf(Paragraph::class, $object->setIndentFirstLine());
+ self::assertNull($object->getIndentFirstLine());
+ }
+
+ public function testIndentLeft(): void
+ {
+ $rand = mt_rand(0, 255);
+
+ $object = new Paragraph();
+ self::assertNull($object->getIndentLeft());
+ self::assertInstanceOf(Paragraph::class, $object->setIndentLeft($rand));
+ self::assertEquals($rand, $object->getIndentLeft());
+ self::assertInstanceOf(Paragraph::class, $object->setIndentLeft(null));
+ self::assertNull($object->getIndentLeft());
+ self::assertInstanceOf(Paragraph::class, $object->setIndentLeft($rand));
+ self::assertEquals($rand, $object->getIndentLeft());
+ self::assertInstanceOf(Paragraph::class, $object->setIndentLeft());
+ self::assertNull($object->getIndentLeft());
+ }
+
+ public function testIndentRight(): void
+ {
+ $rand = mt_rand(0, 255);
+
+ $object = new Paragraph();
+ self::assertNull($object->getIndentRight());
+ self::assertInstanceOf(Paragraph::class, $object->setIndentRight($rand));
+ self::assertEquals($rand, $object->getIndentRight());
+ self::assertInstanceOf(Paragraph::class, $object->setIndentRight(null));
+ self::assertNull($object->getIndentRight());
+ self::assertInstanceOf(Paragraph::class, $object->setIndentRight($rand));
+ self::assertEquals($rand, $object->getIndentRight());
+ self::assertInstanceOf(Paragraph::class, $object->setIndentRight());
+ self::assertNull($object->getIndentRight());
+ }
+
/**
* Line height.
*/