diff --git a/CHANGELOG.md b/CHANGELOG.md index f93b7ac0f3..5235895506 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Improved TextDirection for styling a cell by @terryzwt in #2429 - Word2007 Reader : Added option to disable loading images by @aelliott1485 in #2450 - HTML Writer : Added border-spacing to default styles for table by @kernusr in #2451 +- Word2007 Reader : Support for table cell borders and margins by @kernusr in #2454 ### Bug fixes diff --git a/src/PhpWord/Reader/Word2007/AbstractPart.php b/src/PhpWord/Reader/Word2007/AbstractPart.php index 418661d6f0..3ab8995f9e 100644 --- a/src/PhpWord/Reader/Word2007/AbstractPart.php +++ b/src/PhpWord/Reader/Word2007/AbstractPart.php @@ -385,9 +385,8 @@ protected function readTable(XMLReader $xmlReader, DOMElement $domNode, $parent, } elseif ('w:tc' == $rowNode->nodeName) { // Cell $cellWidth = $xmlReader->getAttribute('w:w', $rowNode, 'w:tcPr/w:tcW'); $cellStyle = null; - $cellStyleNode = $xmlReader->getElement('w:tcPr', $rowNode); - if (null !== $cellStyleNode) { - $cellStyle = $this->readCellStyle($xmlReader, $cellStyleNode); + if ($xmlReader->elementExists('w:tcPr', $rowNode)) { + $cellStyle = $this->readCellStyle($xmlReader, $rowNode); } $cell = $row->addCell($cellWidth, $cellStyle); @@ -573,7 +572,7 @@ private function readTableIndent(XMLReader $xmlReader, DOMElement $domNode) /** * Read w:tcPr. * - * @return array + * @return null|array */ private function readCellStyle(XMLReader $xmlReader, DOMElement $domNode) { @@ -585,8 +584,24 @@ private function readCellStyle(XMLReader $xmlReader, DOMElement $domNode) 'bgColor' => [self::READ_VALUE, 'w:shd', 'w:fill'], 'noWrap' => [self::READ_VALUE, 'w:noWrap', null, null, true], ]; + $style = null; - return $this->readStyleDefs($xmlReader, $domNode, $styleDefs); + if ($xmlReader->elementExists('w:tcPr', $domNode)) { + $styleNode = $xmlReader->getElement('w:tcPr', $domNode); + + $borders = ['top', 'left', 'bottom', 'right']; + foreach ($borders as $side) { + $ucfSide = ucfirst($side); + + $styleDefs['border' . $ucfSide . 'Size'] = [self::READ_VALUE, 'w:tcBorders/w:' . $side, 'w:sz']; + $styleDefs['border' . $ucfSide . 'Color'] = [self::READ_VALUE, 'w:tcBorders/w:' . $side, 'w:color']; + $styleDefs['border' . $ucfSide . 'Style'] = [self::READ_VALUE, 'w:tcBorders/w:' . $side, 'w:val']; + } + + $style = $this->readStyleDefs($xmlReader, $styleNode, $styleDefs); + } + + return $style; } /** diff --git a/src/PhpWord/Style/Border.php b/src/PhpWord/Style/Border.php index 2ee69be56f..28e340c040 100644 --- a/src/PhpWord/Style/Border.php +++ b/src/PhpWord/Style/Border.php @@ -22,6 +22,8 @@ */ class Border extends AbstractStyle { + const DEFAULT_MARGIN = 1440; // In twips. + /** * Border Top Size. * @@ -106,6 +108,34 @@ class Border extends AbstractStyle */ protected $borderBottomStyle; + /** + * Top margin spacing. + * + * @var float|int + */ + protected $marginTop = self::DEFAULT_MARGIN; + + /** + * Left margin spacing. + * + * @var float|int + */ + protected $marginLeft = self::DEFAULT_MARGIN; + + /** + * Right margin spacing. + * + * @var float|int + */ + protected $marginRight = self::DEFAULT_MARGIN; + + /** + * Bottom margin spacing. + * + * @var float|int + */ + protected $marginBottom = self::DEFAULT_MARGIN; + /** * Get border size. * @@ -501,4 +531,100 @@ public function hasBorder() return $borders !== array_filter($borders, 'is_null'); } + + /** + * Get Margin Top. + * + * @return float|int + */ + public function getMarginTop() + { + return $this->marginTop; + } + + /** + * Set Margin Top. + * + * @param float|int $value + * + * @return self + */ + public function setMarginTop($value = null) + { + $this->marginTop = $this->setNumericVal($value, self::DEFAULT_MARGIN); + + return $this; + } + + /** + * Get Margin Left. + * + * @return float|int + */ + public function getMarginLeft() + { + return $this->marginLeft; + } + + /** + * Set Margin Left. + * + * @param float|int $value + * + * @return self + */ + public function setMarginLeft($value = null) + { + $this->marginLeft = $this->setNumericVal($value, self::DEFAULT_MARGIN); + + return $this; + } + + /** + * Get Margin Right. + * + * @return float|int + */ + public function getMarginRight() + { + return $this->marginRight; + } + + /** + * Set Margin Right. + * + * @param float|int $value + * + * @return self + */ + public function setMarginRight($value = null) + { + $this->marginRight = $this->setNumericVal($value, self::DEFAULT_MARGIN); + + return $this; + } + + /** + * Get Margin Bottom. + * + * @return float|int + */ + public function getMarginBottom() + { + return $this->marginBottom; + } + + /** + * Set Margin Bottom. + * + * @param float|int $value + * + * @return self + */ + public function setMarginBottom($value = null) + { + $this->marginBottom = $this->setNumericVal($value, self::DEFAULT_MARGIN); + + return $this; + } } diff --git a/src/PhpWord/Style/Section.php b/src/PhpWord/Style/Section.php index d4ede285e7..3b08aa5f38 100644 --- a/src/PhpWord/Style/Section.php +++ b/src/PhpWord/Style/Section.php @@ -40,7 +40,6 @@ class Section extends Border */ const DEFAULT_WIDTH = 11905.511811024; // In twips. const DEFAULT_HEIGHT = 16837.79527559; // In twips. - const DEFAULT_MARGIN = 1440; // In twips. const DEFAULT_GUTTER = 0; // In twips. const DEFAULT_HEADER_HEIGHT = 720; // In twips. const DEFAULT_FOOTER_HEIGHT = 720; // In twips. @@ -77,34 +76,6 @@ class Section extends Border */ private $pageSizeH = self::DEFAULT_HEIGHT; - /** - * Top margin spacing. - * - * @var float|int - */ - private $marginTop = self::DEFAULT_MARGIN; - - /** - * Left margin spacing. - * - * @var float|int - */ - private $marginLeft = self::DEFAULT_MARGIN; - - /** - * Right margin spacing. - * - * @var float|int - */ - private $marginRight = self::DEFAULT_MARGIN; - - /** - * Bottom margin spacing. - * - * @var float|int - */ - private $marginBottom = self::DEFAULT_MARGIN; - /** * Page gutter spacing. * @@ -344,102 +315,6 @@ public function setPageSizeH($value = null) return $this; } - /** - * Get Margin Top. - * - * @return float|int - */ - public function getMarginTop() - { - return $this->marginTop; - } - - /** - * Set Margin Top. - * - * @param float|int $value - * - * @return self - */ - public function setMarginTop($value = null) - { - $this->marginTop = $this->setNumericVal($value, self::DEFAULT_MARGIN); - - return $this; - } - - /** - * Get Margin Left. - * - * @return float|int - */ - public function getMarginLeft() - { - return $this->marginLeft; - } - - /** - * Set Margin Left. - * - * @param float|int $value - * - * @return self - */ - public function setMarginLeft($value = null) - { - $this->marginLeft = $this->setNumericVal($value, self::DEFAULT_MARGIN); - - return $this; - } - - /** - * Get Margin Right. - * - * @return float|int - */ - public function getMarginRight() - { - return $this->marginRight; - } - - /** - * Set Margin Right. - * - * @param float|int $value - * - * @return self - */ - public function setMarginRight($value = null) - { - $this->marginRight = $this->setNumericVal($value, self::DEFAULT_MARGIN); - - return $this; - } - - /** - * Get Margin Bottom. - * - * @return float|int - */ - public function getMarginBottom() - { - return $this->marginBottom; - } - - /** - * Set Margin Bottom. - * - * @param float|int $value - * - * @return self - */ - public function setMarginBottom($value = null) - { - $this->marginBottom = $this->setNumericVal($value, self::DEFAULT_MARGIN); - - return $this; - } - /** * Get gutter. * diff --git a/tests/PhpWordTests/Reader/Word2007/StyleTest.php b/tests/PhpWordTests/Reader/Word2007/StyleTest.php index be80dc513e..015a3cfcb7 100644 --- a/tests/PhpWordTests/Reader/Word2007/StyleTest.php +++ b/tests/PhpWordTests/Reader/Word2007/StyleTest.php @@ -17,6 +17,7 @@ namespace PhpOffice\PhpWordTests\Reader\Word2007; +use PhpOffice\PhpWord\SimpleType\Border; use PhpOffice\PhpWord\SimpleType\TblWidth; use PhpOffice\PhpWord\SimpleType\VerticalJc; use PhpOffice\PhpWord\Style; @@ -48,28 +49,6 @@ public function testReadTableLayout(): void self::assertEquals(Table::LAYOUT_FIXED, $elements[0]->getStyle()->getLayout()); } - /** - * Test reading of cell spacing. - */ - public function testReadCellSpacing(): void - { - $documentXml = ' - - - - '; - - $phpWord = $this->getDocumentFromString(['document' => $documentXml]); - - $elements = $phpWord->getSection(0)->getElements(); - self::assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]); - self::assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle()); - /** @var \PhpOffice\PhpWord\Style\Table $tableStyle */ - $tableStyle = $elements[0]->getStyle(); - self::assertEquals(TblWidth::AUTO, $tableStyle->getUnit()); - self::assertEquals(10.5, $tableStyle->getCellSpacing()); - } - /** * Test reading of table position. */ @@ -102,6 +81,90 @@ public function testReadTablePosition(): void self::assertEquals(60, $tableStyle->getTblpY()); } + public function testReadTableCellNoWrap(): void + { + $documentXml = ' + + + + + + + + '; + + $phpWord = $this->getDocumentFromString(['document' => $documentXml]); + + $elements = $phpWord->getSection(0)->getElements(); + self::assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]); + $rows = $elements[0]->getRows(); + $cells = $rows[0]->getCells(); + self::assertTrue($cells[0]->getStyle()->getNoWrap()); + } + + /** + * Test reading of cell spacing. + */ + public function testReadTableCellSpacing(): void + { + $documentXml = ' + + + + '; + + $phpWord = $this->getDocumentFromString(['document' => $documentXml]); + + $elements = $phpWord->getSection(0)->getElements(); + self::assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]); + self::assertInstanceOf('PhpOffice\PhpWord\Style\Table', $elements[0]->getStyle()); + /** @var \PhpOffice\PhpWord\Style\Table $tableStyle */ + $tableStyle = $elements[0]->getStyle(); + self::assertEquals(TblWidth::AUTO, $tableStyle->getUnit()); + self::assertEquals(10.5, $tableStyle->getCellSpacing()); + } + + public function testReadTableCellStyle(): void + { + $documentXml = ' + + + + + + + + + + + + + + + + + '; + + $phpWord = $this->getDocumentFromString(['document' => $documentXml]); + + $elements = $phpWord->getSection(0)->getElements(); + self::assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]); + $rows = $elements[0]->getRows(); + self::assertInstanceOf('PhpOffice\PhpWord\Element\Row', $rows[0]); + $cells = $rows[0]->getCells(); + self::assertInstanceOf('PhpOffice\PhpWord\Element\Cell', $cells[0]); + $styleCell = $cells[0]->getStyle(); + self::assertInstanceOf('PhpOffice\PhpWord\Style\Cell', $styleCell); + + self::assertEquals(4, $styleCell->getBorderTopSize()); + self::assertEquals(Border::SINGLE, $styleCell->getBorderTopStyle()); + self::assertEquals('auto', $styleCell->getBorderTopColor()); + + self::assertEquals(4, $styleCell->getBorderBottomSize()); + self::assertEquals(Border::DOUBLE, $styleCell->getBorderBottomStyle()); + self::assertEquals('auto', $styleCell->getBorderBottomColor()); + } + /** * Test reading of position. */ @@ -190,27 +253,6 @@ public function testReadHidden(): void self::assertTrue($fontStyle->isHidden()); } - public function testReadTableCellNoWrap(): void - { - $documentXml = ' - - - - - - - - '; - - $phpWord = $this->getDocumentFromString(['document' => $documentXml]); - - $elements = $phpWord->getSection(0)->getElements(); - self::assertInstanceOf('PhpOffice\PhpWord\Element\Table', $elements[0]); - $rows = $elements[0]->getRows(); - $cells = $rows[0]->getCells(); - self::assertTrue($cells[0]->getStyle()->getNoWrap()); - } - public function testReadHeading(): void { Style::resetStyles();