Skip to content

Commit

Permalink
Word2007 Writer : Added support for field REF (#2652)
Browse files Browse the repository at this point in the history
* added support for REF field

* Spelling correction

* UnitTest and fixes

* updated documentation

* Update doc docs/elements.rst. Aded ref support

* Rebase & Fixed CI

---------

Co-authored-by: Adekunle <[email protected]>
Co-authored-by: Adekunle Adekoya <[email protected]>
  • Loading branch information
3 people authored Aug 12, 2024
1 parent 91cef47 commit 00febf5
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 8 deletions.
1 change: 1 addition & 0 deletions docs/changes/2.x/2.0.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- IOFactory : Added extractVariables method to extract variables from a document [@sibalonat](https://github.com/sibalonat) in [#2515](https://github.com/PHPOffice/PHPWord/pull/2515)
- PDF Writer : Documented how to specify a PDF renderer, when working with the PDF writer, as well as the three available choices by [@settermjd](https://github.com/settermjd) in [#2642](https://github.com/PHPOffice/PHPWord/pull/2642)
- Word2007 Reader: Support for Paragraph Border Style by [@damienfa](https://github.com/damienfa) in [#2651](https://github.com/PHPOffice/PHPWord/pull/2651)
- Word2007 Writer: Support for field REF by [@crystoline](https://github.com/crystoline) in [#2652](https://github.com/PHPOffice/PHPWord/pull/2652)

### Bug fixes

Expand Down
15 changes: 12 additions & 3 deletions docs/usage/elements/field.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Currently the following fields are supported:
- XE
- INDEX
- FILENAME
- REF

``` php
<?php
Expand All @@ -25,16 +26,24 @@ For instance for the INDEX field, you can do the following (See `Index Field for
``` php
<?php

//the $fieldText can be either a simple string
// the $fieldText can be either a simple string
$fieldText = 'The index value';

//or a 'TextRun', to be able to format the text you want in the index
// or a 'TextRun', to be able to format the text you want in the index
$fieldText = new TextRun();
$fieldText->addText('My ');
$fieldText->addText('bold index', ['bold' => true]);
$fieldText->addText(' entry');
$section->addField('XE', array(), array(), $fieldText);

//this actually adds the index
// this actually adds the index
$section->addField('INDEX', array(), array('\\e " " \\h "A" \\c "3"'), 'right click to update index');

// Adding reference to a bookmark
$fieldText->addField('REF', [
'name' => 'bookmark'
], [
'InsertParagraphNumberRelativeContext',
'CreateHyperLink',
]);
```
4 changes: 4 additions & 0 deletions src/PhpWord/Element/Field.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ class Field extends AbstractElement
],
'options' => ['Path', 'PreserveFormat'],
],
'REF' => [
'properties' => ['name' => ''],
'options' => ['f', 'h', 'n', 'p', 'r', 't', 'w'],
],
];

/**
Expand Down
113 changes: 108 additions & 5 deletions src/PhpWord/Writer/Word2007/Element/Field.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@

namespace PhpOffice\PhpWord\Writer\Word2007\Element;

use PhpOffice\PhpWord\Element\Field as ElementField;
use PhpOffice\PhpWord\Element\TextRun;

/**
* Field element writer.
*
Expand All @@ -30,7 +33,7 @@ class Field extends Text
public function write(): void
{
$element = $this->getElement();
if (!$element instanceof \PhpOffice\PhpWord\Element\Field) {
if (!$element instanceof ElementField) {
return;
}

Expand All @@ -42,7 +45,7 @@ public function write(): void
}
}

private function writeDefault(\PhpOffice\PhpWord\Element\Field $element): void
private function writeDefault(ElementField $element): void
{
$xmlWriter = $this->getXmlWriter();
$this->startElementP();
Expand Down Expand Up @@ -73,7 +76,7 @@ private function writeDefault(\PhpOffice\PhpWord\Element\Field $element): void
$xmlWriter->endElement(); // w:r

if ($element->getText() != null) {
if ($element->getText() instanceof \PhpOffice\PhpWord\Element\TextRun) {
if ($element->getText() instanceof TextRun) {
$containerWriter = new Container($xmlWriter, $element->getText(), true);
$containerWriter->write();

Expand Down Expand Up @@ -120,7 +123,7 @@ private function writeDefault(\PhpOffice\PhpWord\Element\Field $element): void
*
* //TODO A lot of code duplication with general method, should maybe be refactored
*/
protected function writeMacrobutton(\PhpOffice\PhpWord\Element\Field $element): void
protected function writeMacrobutton(ElementField $element): void
{
$xmlWriter = $this->getXmlWriter();
$this->startElementP();
Expand Down Expand Up @@ -159,7 +162,7 @@ protected function writeMacrobutton(\PhpOffice\PhpWord\Element\Field $element):
$this->endElementP(); // w:p
}

private function buildPropertiesAndOptions(\PhpOffice\PhpWord\Element\Field $element)
private function buildPropertiesAndOptions(ElementField $element)
{
$propertiesAndOptions = '';
$properties = $element->getProperties();
Expand Down Expand Up @@ -226,4 +229,104 @@ private function buildPropertiesAndOptions(\PhpOffice\PhpWord\Element\Field $ele

return $propertiesAndOptions;
}

/**
* Writes a REF field.
*/
protected function writeRef(ElementField $element): void
{
$xmlWriter = $this->getXmlWriter();
$this->startElementP();

$xmlWriter->startElement('w:r');
$xmlWriter->startElement('w:fldChar');
$xmlWriter->writeAttribute('w:fldCharType', 'begin');
$xmlWriter->endElement(); // w:fldChar
$xmlWriter->endElement(); // w:r

$instruction = ' ' . $element->getType() . ' ';

foreach ($element->getProperties() as $property) {
$instruction .= $property . ' ';
}
foreach ($element->getOptions() as $optionKey => $optionValue) {
$instruction .= $this->convertRefOption($optionKey, $optionValue) . ' ';
}

$xmlWriter->startElement('w:r');
$this->writeFontStyle();
$xmlWriter->startElement('w:instrText');
$xmlWriter->writeAttribute('xml:space', 'preserve');
$xmlWriter->text($instruction);
$xmlWriter->endElement(); // w:instrText
$xmlWriter->endElement(); // w:r

if ($element->getText() != null) {
if ($element->getText() instanceof \PhpOffice\PhpWord\Element\TextRun) {
$containerWriter = new Container($xmlWriter, $element->getText(), true);
$containerWriter->write();

$xmlWriter->startElement('w:r');
$xmlWriter->startElement('w:instrText');
$xmlWriter->text('"' . $this->buildPropertiesAndOptions($element));
$xmlWriter->endElement(); // w:instrText
$xmlWriter->endElement(); // w:r

$xmlWriter->startElement('w:r');
$xmlWriter->startElement('w:instrText');
$xmlWriter->writeAttribute('xml:space', 'preserve');
$xmlWriter->text(' ');
$xmlWriter->endElement(); // w:instrText
$xmlWriter->endElement(); // w:r
}
}

$xmlWriter->startElement('w:r');
$xmlWriter->startElement('w:fldChar');
$xmlWriter->writeAttribute('w:fldCharType', 'separate');
$xmlWriter->endElement(); // w:fldChar
$xmlWriter->endElement(); // w:r

$xmlWriter->startElement('w:r');
$xmlWriter->startElement('w:rPr');
$xmlWriter->startElement('w:noProof');
$xmlWriter->endElement(); // w:noProof
$xmlWriter->endElement(); // w:rPr
$xmlWriter->writeElement('w:t', $element->getText() != null && is_string($element->getText()) ? $element->getText() : '1');
$xmlWriter->endElement(); // w:r

$xmlWriter->startElement('w:r');
$xmlWriter->startElement('w:fldChar');
$xmlWriter->writeAttribute('w:fldCharType', 'end');
$xmlWriter->endElement(); // w:fldChar
$xmlWriter->endElement(); // w:r

$this->endElementP(); // w:p
}

private function convertRefOption(string $optionKey, string $optionValue): string
{
if ($optionKey === 'NumberSeperatorSequence') {
return '\\d ' . $optionValue;
}

switch ($optionValue) {
case 'IncrementAndInsertText':
return '\\f';
case 'CreateHyperLink':
return '\\h';
case 'NoTrailingPeriod':
return '\\n';
case 'IncludeAboveOrBelow':
return '\\p';
case 'InsertParagraphNumberRelativeContext':
return '\\r';
case 'SuppressNonDelimiterNonNumericalText':
return '\\t';
case 'InsertParagraphNumberFullContext':
return '\\w';
default:
return '';
}
}
}
73 changes: 73 additions & 0 deletions tests/PhpWordTests/Writer/Word2007/Element/FieldTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?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
*/

namespace PhpOffice\PhpWordTests\Writer\Word2007\Element;

use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWordTests\TestHelperDOCX;
use PHPUnit\Framework\TestCase;

/**
* Test class for PhpOffice\PhpWord\Writer\Word2007\Field.
*/
class FieldTest extends TestCase
{
/**
* Executed before each method of the class.
*/
protected function tearDown(): void
{
TestHelperDOCX::clear();
}

/**
* Test Field write.
*/
public function testWriteWithRefType(): void
{
$phpWord = new PhpWord();
$section = $phpWord->addSection();
$section->addField(
'REF',
[
'name' => 'my-bookmark',
],
[
'InsertParagraphNumberRelativeContext',
'CreateHyperLink',
]
);

$section->addListItem('line one item');
$section->addListItem('line two item');
$section->addBookmark('my-bookmark');
$section->addListItem('line three item');

$doc = TestHelperDOCX::getDocument($phpWord, 'Word2007');

$refFieldPath = '/w:document/w:body/w:p[1]/w:r[2]/w:instrText';
self::assertTrue($doc->elementExists($refFieldPath));

$bookMarkElement = $doc->getElement($refFieldPath);
self::assertNotNull($bookMarkElement);
self::assertEquals(' REF my-bookmark \r \h ', $bookMarkElement->textContent);

$bookmarkPath = '/w:document/w:body/w:bookmarkStart';
self::assertTrue($doc->elementExists($bookmarkPath));
self::assertEquals('my-bookmark', $doc->getElementAttribute("$bookmarkPath", 'w:name'));
}
}

0 comments on commit 00febf5

Please sign in to comment.