or
$styles['width'] = (int) $val * 50;
$styles['unit'] = \PhpOffice\PhpWord\SimpleType\TblWidth::PERCENT;
} else {
// e.g. , where "2" = 2px (always pixels)
- $val = (int) $val . 'px';
- $styles['cellSpacing'] = Converter::cssToTwip($val);
+ $styles['cellSpacing'] = Converter::pixelToTwip(self::convertHtmlSize($val));
break;
case 'bgcolor':
@@ -188,7 +191,7 @@ protected static function parseInlineStyle($node, $styles = [])
* Parse a node and add a corresponding element to the parent element.
*
* @param DOMNode $node node to parse
- * @param \PhpOffice\PhpWord\Element\AbstractContainer $element object to add an element corresponding with the node
+ * @param AbstractContainer $element object to add an element corresponding with the node
* @param array $styles Array with all styles
* @param array $data Array to transport data to a next level in the DOM tree, for example level of listitems
*/
@@ -241,6 +244,7 @@ protected static function parseNode($node, $element, $styles = [], $data = []):
'a' => ['Link', $node, $element, $styles, null, null, null],
'input' => ['Input', $node, $element, $styles, null, null, null],
'hr' => ['HorizRule', $node, $element, $styles, null, null, null],
+ 'ruby' => ['Ruby', $node, $element, $styles, null, null, null],
];
$newElement = null;
@@ -279,7 +283,7 @@ protected static function parseNode($node, $element, $styles = [], $data = []):
* Parse child nodes.
*
* @param DOMNode $node
- * @param \PhpOffice\PhpWord\Element\AbstractContainer|Row|Table $element
+ * @param AbstractContainer|Row|Table $element
* @param array $styles
* @param array $data
*/
@@ -301,10 +305,10 @@ protected static function parseChildNodes($node, $element, $styles, $data): void
* Parse paragraph node.
*
* @param DOMNode $node
- * @param \PhpOffice\PhpWord\Element\AbstractContainer $element
+ * @param AbstractContainer $element
* @param array &$styles
*
- * @return \PhpOffice\PhpWord\Element\PageBreak|\PhpOffice\PhpWord\Element\TextRun
+ * @return \PhpOffice\PhpWord\Element\PageBreak|TextRun
*/
protected static function parseParagraph($node, $element, &$styles)
{
@@ -320,7 +324,7 @@ protected static function parseParagraph($node, $element, &$styles)
* Parse input node.
*
* @param DOMNode $node
- * @param \PhpOffice\PhpWord\Element\AbstractContainer $element
+ * @param AbstractContainer $element
* @param array &$styles
*/
protected static function parseInput($node, $element, &$styles): void
@@ -344,11 +348,11 @@ protected static function parseInput($node, $element, &$styles): void
/**
* Parse heading node.
*
- * @param \PhpOffice\PhpWord\Element\AbstractContainer $element
+ * @param AbstractContainer $element
* @param array &$styles
* @param string $argument1 Name of heading style
*
- * @return \PhpOffice\PhpWord\Element\TextRun
+ * @return TextRun
*
* @todo Think of a clever way of defining header styles, now it is only based on the assumption, that
* Heading1 - Heading6 are already defined somewhere
@@ -365,7 +369,7 @@ protected static function parseHeading($element, &$styles, $argument1)
* Parse text node.
*
* @param DOMNode $node
- * @param \PhpOffice\PhpWord\Element\AbstractContainer $element
+ * @param AbstractContainer $element
* @param array &$styles
*/
protected static function parseText($node, $element, &$styles): void
@@ -409,7 +413,7 @@ protected static function parseSpan($node, &$styles): void
* Parse table node.
*
* @param DOMNode $node
- * @param \PhpOffice\PhpWord\Element\AbstractContainer $element
+ * @param AbstractContainer $element
* @param array &$styles
*
* @return Table $element
@@ -441,7 +445,7 @@ protected static function parseTable($node, $element, &$styles)
* Parse a table row.
*
* @param DOMNode $node
- * @param \PhpOffice\PhpWord\Element\Table $element
+ * @param Table $element
* @param array &$styles
*
* @return Row $element
@@ -464,10 +468,10 @@ protected static function parseRow($node, $element, &$styles)
* Parse table cell.
*
* @param DOMNode $node
- * @param \PhpOffice\PhpWord\Element\Table $element
+ * @param Table $element
* @param array &$styles
*
- * @return \PhpOffice\PhpWord\Element\Cell|\PhpOffice\PhpWord\Element\TextRun $element
+ * @return \PhpOffice\PhpWord\Element\Cell|TextRun $element
*/
protected static function parseCell($node, $element, &$styles)
{
@@ -558,7 +562,7 @@ protected static function filterOutNonInheritedStyles(array $styles)
* Parse list node.
*
* @param DOMNode $node
- * @param \PhpOffice\PhpWord\Element\AbstractContainer $element
+ * @param AbstractContainer $element
* @param array &$styles
* @param array &$data
*/
@@ -631,15 +635,15 @@ protected static function getListStyle($isOrderedList)
return [
'type' => 'hybridMultilevel',
'levels' => [
- ['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 720, 'left' => 720, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'],
- ['format' => NumberFormat::BULLET, 'text' => 'o', 'alignment' => 'left', 'tabPos' => 1440, 'left' => 1440, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'],
- ['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 2160, 'left' => 2160, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'],
- ['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 2880, 'left' => 2880, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'],
- ['format' => NumberFormat::BULLET, 'text' => 'o', 'alignment' => 'left', 'tabPos' => 3600, 'left' => 3600, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'],
- ['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 4320, 'left' => 4320, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'],
- ['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 5040, 'left' => 5040, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'],
- ['format' => NumberFormat::BULLET, 'text' => 'o', 'alignment' => 'left', 'tabPos' => 5760, 'left' => 5760, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'],
- ['format' => NumberFormat::BULLET, 'text' => '', 'alignment' => 'left', 'tabPos' => 6480, 'left' => 6480, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'],
+ ['format' => NumberFormat::BULLET, 'text' => '•', 'alignment' => 'left', 'tabPos' => 720, 'left' => 720, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'],
+ ['format' => NumberFormat::BULLET, 'text' => '◦', 'alignment' => 'left', 'tabPos' => 1440, 'left' => 1440, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'],
+ ['format' => NumberFormat::BULLET, 'text' => '•', 'alignment' => 'left', 'tabPos' => 2160, 'left' => 2160, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'],
+ ['format' => NumberFormat::BULLET, 'text' => '•', 'alignment' => 'left', 'tabPos' => 2880, 'left' => 2880, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'],
+ ['format' => NumberFormat::BULLET, 'text' => '◦', 'alignment' => 'left', 'tabPos' => 3600, 'left' => 3600, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'],
+ ['format' => NumberFormat::BULLET, 'text' => '•', 'alignment' => 'left', 'tabPos' => 4320, 'left' => 4320, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'],
+ ['format' => NumberFormat::BULLET, 'text' => '•', 'alignment' => 'left', 'tabPos' => 5040, 'left' => 5040, 'hanging' => 360, 'font' => 'Symbol', 'hint' => 'default'],
+ ['format' => NumberFormat::BULLET, 'text' => '◦', 'alignment' => 'left', 'tabPos' => 5760, 'left' => 5760, 'hanging' => 360, 'font' => 'Courier New', 'hint' => 'default'],
+ ['format' => NumberFormat::BULLET, 'text' => '•', 'alignment' => 'left', 'tabPos' => 6480, 'left' => 6480, 'hanging' => 360, 'font' => 'Wingdings', 'hint' => 'default'],
],
];
}
@@ -648,7 +652,7 @@ protected static function getListStyle($isOrderedList)
* Parse list item node.
*
* @param DOMNode $node
- * @param \PhpOffice\PhpWord\Element\AbstractContainer $element
+ * @param AbstractContainer $element
* @param array &$styles
* @param array $data
*
@@ -708,6 +712,10 @@ protected static function parseStyleDeclarations(array $selectors, array $styles
case 'text-align':
$styles['alignment'] = self::mapAlign($value, $bidi);
+ break;
+ case 'ruby-align':
+ $styles['rubyAlignment'] = self::mapRubyAlign($value);
+
break;
case 'display':
$styles['hidden'] = $value === 'none' || $value === 'hidden';
@@ -807,6 +815,58 @@ protected static function parseStyleDeclarations(array $selectors, array $styles
$styles['spaceAfter'] = Converter::cssToTwip($value);
break;
+
+ case 'padding':
+ $valueTop = $valueRight = $valueBottom = $valueLeft = null;
+ $cValue = preg_replace('# +#', ' ', trim($value));
+ $paddingArr = explode(' ', $cValue);
+ $countParams = count($paddingArr);
+ if ($countParams == 1) {
+ $valueTop = $valueRight = $valueBottom = $valueLeft = $paddingArr[0];
+ } elseif ($countParams == 2) {
+ $valueTop = $valueBottom = $paddingArr[0];
+ $valueRight = $valueLeft = $paddingArr[1];
+ } elseif ($countParams == 3) {
+ $valueTop = $paddingArr[0];
+ $valueRight = $valueLeft = $paddingArr[1];
+ $valueBottom = $paddingArr[2];
+ } elseif ($countParams == 4) {
+ $valueTop = $paddingArr[0];
+ $valueRight = $paddingArr[1];
+ $valueBottom = $paddingArr[2];
+ $valueLeft = $paddingArr[3];
+ }
+ if ($valueTop !== null) {
+ $styles['paddingTop'] = Converter::cssToTwip($valueTop);
+ }
+ if ($valueRight !== null) {
+ $styles['paddingRight'] = Converter::cssToTwip($valueRight);
+ }
+ if ($valueBottom !== null) {
+ $styles['paddingBottom'] = Converter::cssToTwip($valueBottom);
+ }
+ if ($valueLeft !== null) {
+ $styles['paddingLeft'] = Converter::cssToTwip($valueLeft);
+ }
+
+ break;
+ case 'padding-top':
+ $styles['paddingTop'] = Converter::cssToTwip($value);
+
+ break;
+ case 'padding-right':
+ $styles['paddingRight'] = Converter::cssToTwip($value);
+
+ break;
+ case 'padding-bottom':
+ $styles['paddingBottom'] = Converter::cssToTwip($value);
+
+ break;
+ case 'padding-left':
+ $styles['paddingLeft'] = Converter::cssToTwip($value);
+
+ break;
+
case 'border-color':
self::mapBorderColor($styles, $value);
@@ -907,7 +967,7 @@ protected static function parseStyleDeclarations(array $selectors, array $styles
* Parse image node.
*
* @param DOMNode $node
- * @param \PhpOffice\PhpWord\Element\AbstractContainer $element
+ * @param AbstractContainer $element
*
* @return \PhpOffice\PhpWord\Element\Image
*/
@@ -922,36 +982,12 @@ protected static function parseImage($node, $element)
break;
case 'width':
- $width = $attribute->value;
-
- // pt
- if (false !== strpos($width, 'pt')) {
- $width = Converter::pointToPixel((float) str_replace('pt', '', $width));
- }
-
- // px
- if (false !== strpos($width, 'px')) {
- $width = str_replace('px', '', $width);
- }
-
- $style['width'] = $width;
+ $style['width'] = self::convertHtmlSize($attribute->value);
$style['unit'] = \PhpOffice\PhpWord\Style\Image::UNIT_PX;
break;
case 'height':
- $height = $attribute->value;
-
- // pt
- if (false !== strpos($height, 'pt')) {
- $height = Converter::pointToPixel((float) str_replace('pt', '', $height));
- }
-
- // px
- if (false !== strpos($height, 'px')) {
- $height = str_replace('px', '', $height);
- }
-
- $style['height'] = $height;
+ $style['height'] = self::convertHtmlSize($attribute->value);
$style['unit'] = \PhpOffice\PhpWord\Style\Image::UNIT_PX;
break;
@@ -991,14 +1027,15 @@ protected static function parseImage($node, $element)
$match = [];
preg_match('/data:image\/(\w+);base64,(.+)/', $src, $match);
+ if (!empty($match)) {
+ $src = $imgFile = $tmpDir . uniqid() . '.' . $match[1];
- $src = $imgFile = $tmpDir . uniqid() . '.' . $match[1];
-
- $ifp = fopen($imgFile, 'wb');
+ $ifp = fopen($imgFile, 'wb');
- if ($ifp !== false) {
- fwrite($ifp, base64_decode($match[2]));
- fclose($ifp);
+ if ($ifp !== false) {
+ fwrite($ifp, base64_decode($match[2]));
+ fclose($ifp);
+ }
}
}
$src = urldecode($src);
@@ -1096,6 +1133,23 @@ protected static function mapAlign($cssAlignment, $bidi)
}
}
+ /**
+ * Transforms a HTML/CSS ruby alignment into a \PhpOffice\PhpWord\SimpleType\Jc.
+ */
+ protected static function mapRubyAlign(string $cssRubyAlignment): string
+ {
+ switch ($cssRubyAlignment) {
+ case 'center':
+ return RubyProperties::ALIGNMENT_CENTER;
+ case 'start':
+ return RubyProperties::ALIGNMENT_LEFT;
+ case 'space-between':
+ return RubyProperties::ALIGNMENT_DISTRIBUTE_SPACE;
+ default:
+ return '';
+ }
+ }
+
/**
* Transforms a HTML/CSS vertical alignment.
*
@@ -1152,7 +1206,7 @@ protected static function mapListType($cssListType)
/**
* Parse line break.
*
- * @param \PhpOffice\PhpWord\Element\AbstractContainer $element
+ * @param AbstractContainer $element
*/
protected static function parseLineBreak($element): void
{
@@ -1163,7 +1217,7 @@ protected static function parseLineBreak($element): void
* Parse link node.
*
* @param DOMNode $node
- * @param \PhpOffice\PhpWord\Element\AbstractContainer $element
+ * @param AbstractContainer $element
* @param array $styles
*/
protected static function parseLink($node, $element, &$styles)
@@ -1179,7 +1233,11 @@ protected static function parseLink($node, $element, &$styles)
}
$styles['font'] = self::parseInlineStyle($node, $styles['font']);
- if (strpos($target, '#') === 0) {
+ if (empty($target)) {
+ $target = '#';
+ }
+
+ if (strpos($target, '#') === 0 && strlen($target) > 1) {
return $element->addLink(substr($target, 1), $node->textContent, $styles['font'], $styles['paragraph'], true);
}
@@ -1191,7 +1249,7 @@ protected static function parseLink($node, $element, &$styles)
* Note: Word rule is not the same as HTML's since it does not support width and thus neither alignment.
*
* @param DOMNode $node
- * @param \PhpOffice\PhpWord\Element\AbstractContainer $element
+ * @param AbstractContainer $element
*/
protected static function parseHorizRule($node, $element): void
{
@@ -1220,6 +1278,59 @@ protected static function parseHorizRule($node, $element): void
// - repeated text, e.g. underline "_", because of unpredictable line wrapping
}
+ /**
+ * Parse ruby node.
+ *
+ * @param DOMNode $node
+ * @param AbstractContainer $element
+ * @param array $styles
+ */
+ protected static function parseRuby($node, $element, &$styles)
+ {
+ $rubyProperties = new RubyProperties();
+ $baseTextRun = new TextRun($styles['paragraph']);
+ $rubyTextRun = new TextRun(null);
+ if ($node->hasAttributes()) {
+ $langAttr = $node->attributes->getNamedItem('lang');
+ if ($langAttr !== null) {
+ $rubyProperties->setLanguageId($langAttr->textContent);
+ }
+ $styleAttr = $node->attributes->getNamedItem('style');
+ if ($styleAttr !== null) {
+ $styles = self::parseStyle($styleAttr, $styles['paragraph']);
+ if (isset($styles['rubyAlignment']) && $styles['rubyAlignment'] !== '') {
+ $rubyProperties->setAlignment($styles['rubyAlignment']);
+ }
+ if (isset($styles['size']) && $styles['size'] !== '') {
+ $rubyProperties->setFontSizeForBaseText($styles['size']);
+ }
+ $baseTextRun->setParagraphStyle($styles);
+ }
+ }
+ foreach ($node->childNodes as $child) {
+ if ($child->nodeName === '#text') {
+ $content = trim($child->textContent);
+ if ($content !== '') {
+ $baseTextRun->addText($content);
+ }
+ } elseif ($child->nodeName === 'rt') {
+ $rubyTextRun->addText(trim($child->textContent));
+ if ($child->hasAttributes()) {
+ $styleAttr = $child->attributes->getNamedItem('style');
+ if ($styleAttr !== null) {
+ $styles = self::parseStyle($styleAttr, []);
+ if (isset($styles['size']) && $styles['size'] !== '') {
+ $rubyProperties->setFontFaceSize($styles['size']);
+ }
+ $rubyTextRun->setParagraphStyle($styles);
+ }
+ }
+ }
+ }
+
+ return $element->addRuby($baseTextRun, $rubyTextRun, $rubyProperties);
+ }
+
private static function convertRgb(string $rgb): string
{
if (preg_match(self::RGB_REGEXP, $rgb, $matches) === 1) {
@@ -1228,4 +1339,22 @@ private static function convertRgb(string $rgb): string
return trim($rgb, '# ');
}
+
+ /**
+ * Transform HTML sizes (pt, px) in pixels.
+ */
+ protected static function convertHtmlSize(string $size): float
+ {
+ // pt
+ if (false !== strpos($size, 'pt')) {
+ return Converter::pointToPixel((float) str_replace('pt', '', $size));
+ }
+
+ // px
+ if (false !== strpos($size, 'px')) {
+ return (float) str_replace('px', '', $size);
+ }
+
+ return (float) $size;
+ }
}
diff --git a/src/PhpWord/Shared/Microsoft/PasswordEncoder.php b/src/PhpWord/Shared/Microsoft/PasswordEncoder.php
index d6cf69fc6d..45f9a53632 100644
--- a/src/PhpWord/Shared/Microsoft/PasswordEncoder.php
+++ b/src/PhpWord/Shared/Microsoft/PasswordEncoder.php
@@ -1,4 +1,5 @@
tempDir . DIRECTORY_SEPARATOR . $filenameParts['basename'], 'wb');
- fwrite($handle, $contents);
- fclose($handle);
+ if ($handle) {
+ fwrite($handle, $contents);
+ fclose($handle);
+ }
// Add temp file to zip
$filename = $this->tempDir . DIRECTORY_SEPARATOR . $filenameParts['basename'];
diff --git a/src/PhpWord/SimpleType/Border.php b/src/PhpWord/SimpleType/Border.php
index 6cb42f0467..acd1c1a1b1 100644
--- a/src/PhpWord/SimpleType/Border.php
+++ b/src/PhpWord/SimpleType/Border.php
@@ -1,4 +1,5 @@
vAlign = null;
+
+ return $this;
+ }
+
VerticalJc::validate($value);
$this->vAlign = $this->setEnumVal($value, VerticalJc::values(), $this->vAlign);
@@ -235,7 +262,7 @@ public function setGridSpan($value = null)
/**
* Get vertical merge (rowspan).
*
- * @return string
+ * @return null|string
*/
public function getVMerge()
{
@@ -245,12 +272,18 @@ public function getVMerge()
/**
* Set vertical merge (rowspan).
*
- * @param string $value
+ * @param null|string $value
*
* @return self
*/
public function setVMerge($value = null)
{
+ if ($value === null) {
+ $this->vMerge = null;
+
+ return $this;
+ }
+
$enum = [self::VMERGE_RESTART, self::VMERGE_CONTINUE];
$this->vMerge = $this->setEnumVal($value, $enum, $this->vMerge);
@@ -260,7 +293,7 @@ public function setVMerge($value = null)
/**
* Get shading.
*
- * @return \PhpOffice\PhpWord\Style\Shading
+ * @return Shading
*/
public function getShading()
{
@@ -344,4 +377,84 @@ public function getNoWrap(): bool
{
return $this->noWrap;
}
+
+ /**
+ * Get style padding-top.
+ */
+ public function getPaddingTop(): ?int
+ {
+ return $this->paddingTop;
+ }
+
+ /**
+ * Set style padding-top.
+ *
+ * @return $this
+ */
+ public function setPaddingTop(int $value): self
+ {
+ $this->paddingTop = $value;
+
+ return $this;
+ }
+
+ /**
+ * Get style padding-bottom.
+ */
+ public function getPaddingBottom(): ?int
+ {
+ return $this->paddingBottom;
+ }
+
+ /**
+ * Set style padding-bottom.
+ *
+ * @return $this
+ */
+ public function setPaddingBottom(int $value): self
+ {
+ $this->paddingBottom = $value;
+
+ return $this;
+ }
+
+ /**
+ * Get style padding-left.
+ */
+ public function getPaddingLeft(): ?int
+ {
+ return $this->paddingLeft;
+ }
+
+ /**
+ * Set style padding-left.
+ *
+ * @return $this
+ */
+ public function setPaddingLeft(int $value): self
+ {
+ $this->paddingLeft = $value;
+
+ return $this;
+ }
+
+ /**
+ * Get style padding-right.
+ */
+ public function getPaddingRight(): ?int
+ {
+ return $this->paddingRight;
+ }
+
+ /**
+ * Set style padding-right.
+ *
+ * @return $this
+ */
+ public function setPaddingRight(int $value): self
+ {
+ $this->paddingRight = $value;
+
+ return $this;
+ }
}
diff --git a/src/PhpWord/Style/Chart.php b/src/PhpWord/Style/Chart.php
index 9dbc8db0a6..6cffc4d5b0 100644
--- a/src/PhpWord/Style/Chart.php
+++ b/src/PhpWord/Style/Chart.php
@@ -1,4 +1,5 @@
strikethrough;
}
@@ -577,20 +576,16 @@ public function isStrikethrough()
* Set strikethrough.
*
* @param bool $value
- *
- * @return self
*/
- public function setStrikethrough($value = true)
+ public function setStrikethrough($value = true): self
{
return $this->setPairedVal($this->strikethrough, $this->doubleStrikethrough, $value);
}
/**
* Get double strikethrough.
- *
- * @return bool
*/
- public function isDoubleStrikethrough()
+ public function isDoubleStrikethrough(): ?bool
{
return $this->doubleStrikethrough;
}
@@ -599,10 +594,8 @@ public function isDoubleStrikethrough()
* Set double strikethrough.
*
* @param bool $value
- *
- * @return self
*/
- public function setDoubleStrikethrough($value = true)
+ public function setDoubleStrikethrough($value = true): self
{
return $this->setPairedVal($this->doubleStrikethrough, $this->strikethrough, $value);
}
@@ -690,7 +683,7 @@ public function getBgColor()
*
* @param string $value
*
- * @return \PhpOffice\PhpWord\Style\Table
+ * @return Table
*/
public function setBgColor($value = null)
{
@@ -820,7 +813,7 @@ public function setLineHeight($value)
/**
* Get paragraph style.
*
- * @return \PhpOffice\PhpWord\Style\Paragraph
+ * @return Paragraph
*/
public function getParagraph()
{
@@ -868,7 +861,7 @@ public function setRTL($value = true)
/**
* Get shading.
*
- * @return \PhpOffice\PhpWord\Style\Shading
+ * @return Shading
*/
public function getShading()
{
@@ -892,7 +885,7 @@ public function setShading($value = null)
/**
* Get language.
*
- * @return null|\PhpOffice\PhpWord\Style\Language
+ * @return null|Language
*/
public function getLang()
{
diff --git a/src/PhpWord/Style/Frame.php b/src/PhpWord/Style/Frame.php
index 45fc583ed1..016722f36c 100644
--- a/src/PhpWord/Style/Frame.php
+++ b/src/PhpWord/Style/Frame.php
@@ -1,4 +1,5 @@
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/Language.php b/src/PhpWord/Style/Language.php
index 18e7f76e77..54e4376562 100644
--- a/src/PhpWord/Style/Language.php
+++ b/src/PhpWord/Style/Language.php
@@ -1,4 +1,5 @@
numId;
}
/**
* Set Id.
- *
- * @param int $value
- *
- * @return self
*/
- public function setNumId($value)
+ public function setNumId(int $value): self
{
$this->numId = $this->setIntVal($value, $this->numId);
@@ -78,22 +73,16 @@ public function setNumId($value)
/**
* Get multilevel type.
- *
- * @return string
*/
- public function getType()
+ public function getType(): ?string
{
return $this->type;
}
/**
* Set multilevel type.
- *
- * @param string $value
- *
- * @return self
*/
- public function setType($value)
+ public function setType(string $value): self
{
$enum = ['singleLevel', 'multilevel', 'hybridMultilevel'];
$this->type = $this->setEnumVal($value, $enum, $this->type);
@@ -106,19 +95,15 @@ public function setType($value)
*
* @return NumberingLevel[]
*/
- public function getLevels()
+ public function getLevels(): array
{
return $this->levels;
}
/**
* Set multilevel type.
- *
- * @param array $values
- *
- * @return self
*/
- public function setLevels($values)
+ public function setLevels(array $values): self
{
if (is_array($values)) {
foreach ($values as $key => $value) {
diff --git a/src/PhpWord/Style/NumberingLevel.php b/src/PhpWord/Style/NumberingLevel.php
index 39c0d839d6..31ec3738c8 100644
--- a/src/PhpWord/Style/NumberingLevel.php
+++ b/src/PhpWord/Style/NumberingLevel.php
@@ -1,4 +1,5 @@
getChildStyleValue($this->indentation, 'hanging');
+ }
+
/**
* Get indentation.
*
- * @return null|\PhpOffice\PhpWord\Style\Indentation
+ * @deprecated 1.4.0 Use getIndentLeft
+ */
+ public function getIndent(): ?float
+ {
+ return $this->getChildStyleValue($this->indentation, 'left');
+ }
+
+ /**
+ * Get indentation.
*/
- public function getIndentation()
+ 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.
*
- * @return \PhpOffice\PhpWord\Style\Spacing
+ * @return Spacing
*
* @todo Rename to getSpacing in 1.0
*/
@@ -474,7 +533,7 @@ public function getSpacingLineRule()
*
* @param string $value Possible values are defined in LineSpacingRule
*
- * @return \PhpOffice\PhpWord\Style\Paragraph
+ * @return Paragraph
*/
public function setSpacingLineRule($value)
{
@@ -662,7 +721,7 @@ public function setNumLevel($value = 0)
/**
* Get tabs.
*
- * @return \PhpOffice\PhpWord\Style\Tab[]
+ * @return Tab[]
*/
public function getTabs()
{
@@ -688,7 +747,7 @@ public function setTabs($value = null)
/**
* Get shading.
*
- * @return \PhpOffice\PhpWord\Style\Shading
+ * @return Shading
*/
public function getShading()
{
diff --git a/src/PhpWord/Style/Row.php b/src/PhpWord/Style/Row.php
index 765c54f80e..31ae3dedc1 100644
--- a/src/PhpWord/Style/Row.php
+++ b/src/PhpWord/Style/Row.php
@@ -1,4 +1,5 @@
zip()->AddFromString("word/media/image1.jpg", file_get_contents($file));
* To read a file: $templateProcessor->zip()->getFromName("word/media/image1.jpg");
*
- * @return \PhpOffice\PhpWord\Shared\ZipArchive
+ * @return ZipArchive
*/
public function zip()
{
@@ -281,7 +281,7 @@ public function setComplexValue($search, Element\AbstractElement $complexType):
$objectClass = 'PhpOffice\\PhpWord\\Writer\\Word2007\\Element\\' . $elementName;
$xmlWriter = new XMLWriter();
- /** @var \PhpOffice\PhpWord\Writer\Word2007\Element\AbstractElement $elementWriter */
+ /** @var Writer\Word2007\Element\AbstractElement $elementWriter */
$elementWriter = new $objectClass($xmlWriter, $complexType, true);
$elementWriter->write();
@@ -308,7 +308,7 @@ public function setComplexBlock($search, Element\AbstractElement $complexType):
$objectClass = 'PhpOffice\\PhpWord\\Writer\\Word2007\\Element\\' . $elementName;
$xmlWriter = new XMLWriter();
- /** @var \PhpOffice\PhpWord\Writer\Word2007\Element\AbstractElement $elementWriter */
+ /** @var Writer\Word2007\Element\AbstractElement $elementWriter */
$elementWriter = new $objectClass($xmlWriter, $complexType, false);
$elementWriter->write();
@@ -406,7 +406,7 @@ public function setChart($search, Element\AbstractElement $chart): void
$filename = "charts/chart{$rId}.xml";
// Get the part writer
- $writerPart = new \PhpOffice\PhpWord\Writer\Word2007\Part\Chart();
+ $writerPart = new Writer\Word2007\Part\Chart();
$writerPart->setElement($chart);
// ContentTypes.xml
@@ -499,20 +499,22 @@ private function fixImageWidthHeightRatio(&$width, &$height, $actualWidth, $actu
$widthFloat = $heightFloat * $imageRatio;
$matches = [];
preg_match('/\\d([a-z%]+)$/', $height, $matches);
- $width = $widthFloat . $matches[1];
+ $width = $widthFloat . (!empty($matches) ? $matches[1] : 'px');
} elseif ($height === '') { // defined height is empty
$widthFloat = (float) $width;
$heightFloat = $widthFloat / $imageRatio;
$matches = [];
preg_match('/\\d([a-z%]+)$/', $width, $matches);
- $height = $heightFloat . $matches[1];
+ $height = $heightFloat . (!empty($matches) ? $matches[1] : 'px');
} else { // we have defined size, but we need also check it aspect ratio
$widthMatches = [];
preg_match('/\\d([a-z%]+)$/', $width, $widthMatches);
$heightMatches = [];
preg_match('/\\d([a-z%]+)$/', $height, $heightMatches);
// try to fix only if dimensions are same
- if ($widthMatches[1] == $heightMatches[1]) {
+ if (!empty($widthMatches)
+ && !empty($heightMatches)
+ && $widthMatches[1] == $heightMatches[1]) {
$dimention = $widthMatches[1];
$widthFloat = (float) $width;
$heightFloat = (float) $height;
@@ -1287,7 +1289,7 @@ protected function getSlice($startPosition, $endPosition = 0)
* @param int $count
* @param string $xmlBlock
*
- * @return string
+ * @return array
*/
protected function indexClonedVariables($count, $xmlBlock)
{
@@ -1339,7 +1341,7 @@ protected function replaceClonedVariables($variableReplacements, $xmlBlock)
* @param string $block New block content
* @param string $blockType XML tag type of block
*
- * @return \PhpOffice\PhpWord\TemplateProcessor Fluent interface
+ * @return TemplateProcessor Fluent interface
*/
public function replaceXmlBlock($macro, $block, $blockType = 'w:p')
{
diff --git a/src/PhpWord/Writer/AbstractWriter.php b/src/PhpWord/Writer/AbstractWriter.php
index 8ebf98c7b5..13859d8227 100644
--- a/src/PhpWord/Writer/AbstractWriter.php
+++ b/src/PhpWord/Writer/AbstractWriter.php
@@ -1,4 +1,5 @@
parts as $partName) {
$partClass = 'PhpOffice\\PhpWord\\Writer\\HTML\\Part\\' . $partName;
if (class_exists($partClass)) {
- /** @var \PhpOffice\PhpWord\Writer\HTML\Part\AbstractPart $part Type hint */
+ /** @var HTML\Part\AbstractPart $part Type hint */
$part = new $partClass();
$part->setParentWriter($this);
$this->writerParts[strtolower($partName)] = $part;
diff --git a/src/PhpWord/Writer/HTML/Element/AbstractElement.php b/src/PhpWord/Writer/HTML/Element/AbstractElement.php
index 7c7bde3189..0e6a112eed 100644
--- a/src/PhpWord/Writer/HTML/Element/AbstractElement.php
+++ b/src/PhpWord/Writer/HTML/Element/AbstractElement.php
@@ -1,4 +1,5 @@
namespace, $elementClass);
if (class_exists($writerClass)) {
- /** @var \PhpOffice\PhpWord\Writer\HTML\Element\AbstractElement $writer Type hint */
+ /** @var AbstractElement $writer Type hint */
$writer = new $writerClass($this->parentWriter, $element, $withoutP);
$content .= $writer->write();
}
diff --git a/src/PhpWord/Writer/HTML/Element/Endnote.php b/src/PhpWord/Writer/HTML/Element/Endnote.php
index 1c35e8faa8..7e7f31d4fc 100644
--- a/src/PhpWord/Writer/HTML/Element/Endnote.php
+++ b/src/PhpWord/Writer/HTML/Element/Endnote.php
@@ -1,4 +1,5 @@
processFontStyle();
+
+ /** @var \PhpOffice\PhpWord\Element\Ruby $element Type hint */
+ $element = $this->element;
+
+ $baseText = $this->parentWriter->escapeHTML($element->getBaseTextRun()->getText());
+ $rubyText = $this->parentWriter->escapeHTML($element->getRubyTextRun()->getText());
+
+ $rubyTagPropertyCSS = $this->getPropertyCssForRubyTag($element->getProperties());
+ $lang = $element->getProperties()->getLanguageId();
+ $content = "getParagraphStyleForTextRun($element->getBaseTextRun(), $rubyTagPropertyCSS)} lang=\"{$lang}\">";
+ $content .= $baseText;
+ $content .= ' ';
+ $rtTagPropertyCSS = $this->getPropertyCssForRtTag($element->getProperties());
+ $content .= "';
+ $content .= '';
+ $content .= '';
+
+ return $content;
+ }
+
+ /**
+ * Get property CSS for the tag.
+ */
+ private function getPropertyCssForRubyTag(RubyProperties $properties): string
+ {
+ // alignment CSS: https://developer.mozilla.org/en-US/docs/Web/CSS/ruby-align
+ $alignment = 'space-between';
+ switch ($properties->getAlignment()) {
+ case RubyProperties::ALIGNMENT_CENTER:
+ $alignment = 'center';
+
+ break;
+ case RubyProperties::ALIGNMENT_LEFT:
+ $alignment = 'start';
+
+ break;
+ default:
+ $alignment = 'space-between';
+
+ break;
+ }
+
+ return
+ 'font-size:' . $properties->getFontSizeForBaseText() . 'pt' . ';' .
+ 'ruby-align:' . $alignment . ';';
+ }
+
+ /**
+ * Get property CSS for the |