Skip to content

Word2007 Writer : Add PageNumber to TOC #2471

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/changes/1.x/1.2.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
13 changes: 9 additions & 4 deletions docs/usage/elements/title.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,17 @@ If `depth` is 0, a Title will be inserted, otherwise a Heading1, Heading2, ...
<?php

$phpWord->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.
2 changes: 1 addition & 1 deletion src/PhpWord/Element/AbstractContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
21 changes: 20 additions & 1 deletion src/PhpWord/Element/Title.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
}
}

/**
Expand Down Expand Up @@ -106,4 +117,12 @@ public function getStyle()
{
return $this->style;
}

/**
* Get page number.
*/
public function getPageNumber(): ?int
{
return $this->pageNumber;
}
}
24 changes: 17 additions & 7 deletions src/PhpWord/Writer/Word2007/Element/TOC.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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');
Expand All @@ -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();
Expand Down
47 changes: 27 additions & 20 deletions tests/PhpWordTests/Element/TitleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
*
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
declare(strict_types=1);

namespace PhpOffice\PhpWordTests\Element;

Expand All @@ -32,42 +33,48 @@
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());
}

/**
* Create new instance with TextRun.
*/
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());
}
}
56 changes: 56 additions & 0 deletions tests/PhpWordTests/Writer/Word2007/Element/TOCTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php
/**
* This file is part of PHPWord - A pure PHP library for reading and writing
* word processing documents.
*
* PHPWord is free software distributed under the terms of the GNU Lesser
* General Public License version 3 as published by the Free Software Foundation.
*
* For the full copyright and license information, please read the LICENSE
* file that was distributed with this source code. For the full list of
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
*
* @see https://github.com/PHPOffice/PHPWord
*
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
declare(strict_types=1);

namespace PhpOffice\PhpWordTests\Writer\Word2007\Element;

use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWordTests\TestHelperDOCX;

/**
* Test class for PhpOffice\PhpWord\Writer\Word2007\Element subnamespace.
*/
class TOCTest extends \PHPUnit\Framework\TestCase
{
/**
* Executed after each method of the class.
*/
protected function tearDown(): void
{
TestHelperDOCX::clear();
}

public function testWriteTitlePageNumber(): void
{
$expectedPageNum = mt_rand(1, 1000);

$phpWord = new PhpWord();

$section = $phpWord->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);
}
}
96 changes: 96 additions & 0 deletions tests/PhpWordTests/Writer/Word2007/Element/TitleTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php
/**
* This file is part of PHPWord - A pure PHP library for reading and writing
* word processing documents.
*
* PHPWord is free software distributed under the terms of the GNU Lesser
* General Public License version 3 as published by the Free Software Foundation.
*
* For the full copyright and license information, please read the LICENSE
* file that was distributed with this source code. For the full list of
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
*
* @see https://github.com/PHPOffice/PHPWord
*
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
declare(strict_types=1);

namespace PhpOffice\PhpWordTests\Writer\Word2007\Element;

use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWordTests\TestHelperDOCX;

/**
* Test class for PhpOffice\PhpWord\Writer\Word2007\Element subnamespace.
*/
class TitleTest extends \PHPUnit\Framework\TestCase
{
/**
* Executed after each method of the class.
*/
protected function tearDown(): void
{
TestHelperDOCX::clear();
}

public function testWriteTitleWithStyle(): void
{
$phpWord = new PhpWord();
$phpWord->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'));
}
}
Loading