diff --git a/docs/changes/1.x/1.2.0.md b/docs/changes/1.x/1.2.0.md index a6b88ca93c..83b20af735 100644 --- a/docs/changes/1.x/1.2.0.md +++ b/docs/changes/1.x/1.2.0.md @@ -13,6 +13,7 @@ - PDF Writer : Add config for defining the default font by [@MikeMaldini](https://github.com/MikeMaldini) in [#2262](https://github.com/PHPOffice/PHPWord/pull/2262) & [#2468](https://github.com/PHPOffice/PHPWord/pull/2468) - Word2007 Reader : Added support for Comments by [@shaedrich](https://github.com/shaedrich) in [#2161](https://github.com/PHPOffice/PHPWord/pull/2161) & [#2469](https://github.com/PHPOffice/PHPWord/pull/2469) - Word2007 Reader/Writer: Permit book-fold printing by [@potofcoffee](https://github.com/potofcoffee) in [#2225](https://github.com/PHPOffice/PHPWord/pull/2225) & [#2470](https://github.com/PHPOffice/PHPWord/pull/2470) +- Word2007 Writer : Add PageNumber to TOC by [@jet-desk](https://github.com/jet-desk) in [#1652](https://github.com/PHPOffice/PHPWord/pull/1652) & [#2471](https://github.com/PHPOffice/PHPWord/pull/2471) ### Bug fixes diff --git a/docs/usage/elements/title.md b/docs/usage/elements/title.md index f778d6ddb7..fba78ef645 100644 --- a/docs/usage/elements/title.md +++ b/docs/usage/elements/title.md @@ -8,12 +8,17 @@ If `depth` is 0, a Title will be inserted, otherwise a Heading1, Heading2, ... addTitleStyle($depth, [$fontStyle], [$paragraphStyle]); -$section->addTitle($text, [$depth]); +$section->addTitle($text, $depth, $pageNumber); ``` -- ``depth``. -- ``$fontStyle``. See [`Styles > Font`](../styles/font.md). -- ``$paragraphStyle``. See [`Styles > Paragraph`](../styles/paragraph.md). +`addTitleStyle` : +- ``$depth`` +- ``$fontStyle``: See [`Styles > Font`](../styles/font.md). +- ``$paragraphStyle``: See [`Styles > Paragraph`](../styles/paragraph.md). + +`addTitle` : - ``$text``. Text to be displayed in the document. This can be `string` or a `\PhpOffice\PhpWord\Element\TextRun` +- ``$depth`` +- ``$pageNumber`` : Number of the page It's necessary to add a title style to your document because otherwise the title won't be detected as a real title. \ No newline at end of file diff --git a/src/PhpWord/Element/AbstractContainer.php b/src/PhpWord/Element/AbstractContainer.php index 726e204d00..884ec29385 100644 --- a/src/PhpWord/Element/AbstractContainer.php +++ b/src/PhpWord/Element/AbstractContainer.php @@ -34,7 +34,7 @@ * @method Footnote addFootnote(mixed $pStyle = null) * @method Endnote addEndnote(mixed $pStyle = null) * @method CheckBox addCheckBox(string $name, $text, mixed $fStyle = null, mixed $pStyle = null) - * @method Title addTitle(mixed $text, int $depth = 1) + * @method Title addTitle(mixed $text, int $depth = 1, int $pageNumber = null) * @method TOC addTOC(mixed $fontStyle = null, mixed $tocStyle = null, int $minDepth = 1, int $maxDepth = 9) * @method PageBreak addPageBreak() * @method Table addTable(mixed $style = null) diff --git a/src/PhpWord/Element/Title.php b/src/PhpWord/Element/Title.php index 461a03fc5a..8fd5b21b1d 100644 --- a/src/PhpWord/Element/Title.php +++ b/src/PhpWord/Element/Title.php @@ -54,13 +54,20 @@ class Title extends AbstractElement */ protected $collectionRelation = true; + /** + * Page number. + * + * @var int + */ + private $pageNumber; + /** * Create a new Title Element. * * @param string|TextRun $text * @param int $depth */ - public function __construct($text, $depth = 1) + public function __construct($text, $depth = 1, ?int $pageNumber = null) { if (is_string($text)) { $this->text = SharedText::toUTF8($text); @@ -75,6 +82,10 @@ public function __construct($text, $depth = 1) if (array_key_exists($styleName, Style::getStyles())) { $this->style = str_replace('_', '', $styleName); } + + if ($pageNumber !== null) { + $this->pageNumber = $pageNumber; + } } /** @@ -106,4 +117,12 @@ public function getStyle() { return $this->style; } + + /** + * Get page number. + */ + public function getPageNumber(): ?int + { + return $this->pageNumber; + } } diff --git a/src/PhpWord/Writer/Word2007/Element/TOC.php b/src/PhpWord/Writer/Word2007/Element/TOC.php index 90b4ce3d9e..7c5d089775 100644 --- a/src/PhpWord/Writer/Word2007/Element/TOC.php +++ b/src/PhpWord/Writer/Word2007/Element/TOC.php @@ -17,6 +17,7 @@ namespace PhpOffice\PhpWord\Writer\Word2007\Element; +use PhpOffice\PhpWord\Element\Title; use PhpOffice\PhpWord\Element\TOC as TOCElement; use PhpOffice\PhpWord\Shared\XMLWriter; use PhpOffice\PhpWord\Style\Font; @@ -63,11 +64,8 @@ public function write(): void /** * Write title. - * - * @param \PhpOffice\PhpWord\Element\Title $title - * @param bool $writeFieldMark */ - private function writeTitle(XMLWriter $xmlWriter, TOCElement $element, $title, $writeFieldMark): void + private function writeTitle(XMLWriter $xmlWriter, TOCElement $element, Title $title, bool $writeFieldMark): void { $tocStyle = $element->getStyleTOC(); $fontStyle = $element->getStyleFont(); @@ -116,6 +114,20 @@ private function writeTitle(XMLWriter $xmlWriter, TOCElement $element, $title, $ $xmlWriter->endElement(); $xmlWriter->endElement(); + if ($title->getPageNumber() !== null) { + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:fldChar'); + $xmlWriter->writeAttribute('w:fldCharType', 'separate'); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:t'); + $xmlWriter->text((string) $title->getPageNumber()); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } + $xmlWriter->startElement('w:r'); $xmlWriter->startElement('w:fldChar'); $xmlWriter->writeAttribute('w:fldCharType', 'end'); @@ -129,10 +141,8 @@ private function writeTitle(XMLWriter $xmlWriter, TOCElement $element, $title, $ /** * Write style. - * - * @param int $indent */ - private function writeStyle(XMLWriter $xmlWriter, TOCElement $element, $indent): void + private function writeStyle(XMLWriter $xmlWriter, TOCElement $element, int $indent): void { $tocStyle = $element->getStyleTOC(); $fontStyle = $element->getStyleFont(); diff --git a/tests/PhpWordTests/Element/TitleTest.php b/tests/PhpWordTests/Element/TitleTest.php index 0e3e481510..e48a163721 100644 --- a/tests/PhpWordTests/Element/TitleTest.php +++ b/tests/PhpWordTests/Element/TitleTest.php @@ -14,6 +14,7 @@ * * @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3 */ +declare(strict_types=1); namespace PhpOffice\PhpWordTests\Element; @@ -32,24 +33,17 @@ class TitleTest extends \PHPUnit\Framework\TestCase { /** - * Create new instance. + * Create new instance with string. */ public function testConstruct(): void { - $oTitle = new Title('text'); + $title = new Title('text'); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\Title', $oTitle); - self::assertEquals('text', $oTitle->getText()); - } - - /** - * Get style null. - */ - public function testStyleNull(): void - { - $oTitle = new Title('text'); - - self::assertNull($oTitle->getStyle()); + self::assertInstanceOf(Title::class, $title); + self::assertEquals('text', $title->getText()); + self::assertEquals(1, $title->getDepth()); + self::assertNull($title->getPageNumber()); + self::assertNull($title->getStyle()); } /** @@ -57,17 +51,30 @@ public function testStyleNull(): void */ public function testConstructWithTextRun(): void { - $oTextRun = new TextRun(); - $oTextRun->addText('text'); - $oTitle = new Title($oTextRun); + $textRun = new TextRun(); + $textRun->addText('text'); + $title = new Title($textRun); - self::assertInstanceOf('PhpOffice\\PhpWord\\Element\\TextRun', $oTitle->getText()); + self::assertInstanceOf(TextRun::class, $title->getText()); + self::assertEquals(1, $title->getDepth()); + self::assertNull($title->getPageNumber()); + self::assertNull($title->getStyle()); } public function testConstructWithInvalidArgument(): void { $this->expectException(InvalidArgumentException::class); - $oPageBreak = new PageBreak(); - new Title($oPageBreak); + + new Title(new PageBreak()); + } + + public function testConstructWithPageNumber(): void + { + $title = new Title('text', 1, 0); + + self::assertInstanceOf(Title::class, $title); + self::assertEquals('text', $title->getText()); + self::assertEquals(0, $title->getPageNumber()); + self::assertNull($title->getStyle()); } } diff --git a/tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php b/tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php new file mode 100644 index 0000000000..537fb93d1a --- /dev/null +++ b/tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php @@ -0,0 +1,56 @@ +addSection(); + $section->addTOC(); + $section->addTitle('TestTitle 1', 1, $expectedPageNum); + + $doc = TestHelperDOCX::getDocument($phpWord); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:hyperlink/w:r[1]/w:t')); + self::assertEquals('TestTitle 1', $doc->getElement('/w:document/w:body/w:p[1]/w:hyperlink/w:r[1]/w:t')->textContent); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:hyperlink/w:r[5]/w:fldChar')); + self::assertEquals('separate', $doc->getElementAttribute('/w:document/w:body/w:p[1]/w:hyperlink/w:r[5]/w:fldChar', 'w:fldCharType')); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:hyperlink/w:r[6]/w:t')); + self::assertEquals($expectedPageNum, $doc->getElement('/w:document/w:body/w:p[1]/w:hyperlink/w:r[6]/w:t')->textContent); + } +} diff --git a/tests/PhpWordTests/Writer/Word2007/Element/TitleTest.php b/tests/PhpWordTests/Writer/Word2007/Element/TitleTest.php new file mode 100644 index 0000000000..180a319eb1 --- /dev/null +++ b/tests/PhpWordTests/Writer/Word2007/Element/TitleTest.php @@ -0,0 +1,96 @@ +addTitleStyle(0, ['size' => 14, 'italic' => true]); + + $section = $phpWord->addSection(); + $section->addTitle('Test Title0', 0); + + $doc = TestHelperDOCX::getDocument($phpWord); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:r/w:t')); + self::assertEquals('Test Title0', $doc->getElement('/w:document/w:body/w:p[1]/w:r/w:t')->textContent); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:pPr/w:pStyle')); + self::assertEquals('Title', $doc->getElementAttribute('/w:document/w:body/w:p[1]/w:pPr/w:pStyle', 'w:val')); + } + + public function testWriteTitleWithoutStyle(): void + { + $phpWord = new PhpWord(); + + $section = $phpWord->addSection(); + $section->addTitle('Test Title0', 0); + + $doc = TestHelperDOCX::getDocument($phpWord); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:r/w:t')); + self::assertEquals('Test Title0', $doc->getElement('/w:document/w:body/w:p[1]/w:r/w:t')->textContent); + self::assertFalse($doc->elementExists('/w:document/w:body/w:p[1]/w:pPr')); + } + + public function testWriteHeadingWithStyle(): void + { + $phpWord = new PhpWord(); + $phpWord->addTitleStyle(1, ['bold' => true], ['spaceAfter' => 240]); + + $section = $phpWord->addSection(); + $section->addTitle('TestHeading 1', 1); + + $doc = TestHelperDOCX::getDocument($phpWord); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:r/w:t')); + self::assertEquals('TestHeading 1', $doc->getElement('/w:document/w:body/w:p[1]/w:r/w:t')->textContent); + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:pPr/w:pStyle')); + self::assertEquals('Heading1', $doc->getElementAttribute('/w:document/w:body/w:p[1]/w:pPr/w:pStyle', 'w:val')); + } + + public function testWriteHeadingWithoutStyle(): void + { + $phpWord = new PhpWord(); + + $section = $phpWord->addSection(); + $section->addTitle('TestHeading 1', 1); + + $doc = TestHelperDOCX::getDocument($phpWord); + + self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:r/w:t')); + self::assertEquals('TestHeading 1', $doc->getElement('/w:document/w:body/w:p[1]/w:r/w:t')->textContent); + self::assertFalse($doc->elementExists('/w:document/w:body/w:p[1]/w:pPr')); + } +} diff --git a/tests/PhpWordTests/Writer/Word2007/ElementTest.php b/tests/PhpWordTests/Writer/Word2007/ElementTest.php index 41c86f6b84..3bcd842fbd 100644 --- a/tests/PhpWordTests/Writer/Word2007/ElementTest.php +++ b/tests/PhpWordTests/Writer/Word2007/ElementTest.php @@ -460,32 +460,6 @@ public function testTrackChange(): void self::assertTrue($doc->elementExists('/w:document/w:body/w:p/w:del/w:r/w:delText')); } - /** - * Test Title and Headings. - */ - public function testTitleAndHeading(): void - { - $phpWord = new PhpWord(); - $phpWord->addTitleStyle(0, ['size' => 14, 'italic' => true]); - $phpWord->addTitleStyle(1, ['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); - - self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:r/w:t')); - self::assertEquals('This is a title', $doc->getElement('/w:document/w:body/w:p[1]/w:r/w:t')->textContent); - self::assertTrue($doc->elementExists('/w:document/w:body/w:p[1]/w:pPr/w:pStyle')); - self::assertEquals('Title', $doc->getElementAttribute('/w:document/w:body/w:p[1]/w:pPr/w:pStyle', 'w:val')); - - self::assertTrue($doc->elementExists('/w:document/w:body/w:p[2]/w:r/w:t')); - self::assertEquals('Heading 1', $doc->getElement('/w:document/w:body/w:p[2]/w:r/w:t')->textContent); - self::assertTrue($doc->elementExists('/w:document/w:body/w:p[2]/w:pPr/w:pStyle')); - self::assertEquals('Heading1', $doc->getElementAttribute('/w:document/w:body/w:p[2]/w:pPr/w:pStyle', 'w:val')); - } - /** * Test correct writing of text with ampersant in it. */ diff --git a/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php b/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php index 04bdb54ed7..108142d6f2 100644 --- a/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php +++ b/tests/PhpWordTests/Writer/Word2007/Part/DocumentTest.php @@ -436,20 +436,6 @@ public function testWriteWatermark(): void self::assertStringStartsWith('rId', $element->getAttribute('r:id')); } - /** - * covers ::_writeTitle. - */ - public function testWriteTitle(): void - { - $phpWord = new PhpWord(); - $phpWord->addTitleStyle(1, ['bold' => true], ['spaceAfter' => 240]); - $phpWord->addSection()->addTitle('Test', 1); - $doc = TestHelperDOCX::getDocument($phpWord); - - $element = '/w:document/w:body/w:p/w:pPr/w:pStyle'; - self::assertEquals('Heading1', $doc->getElementAttribute($element, 'w:val')); - } - /** * covers ::_writeCheckbox. */