diff --git a/docs/usage/elements/field.md b/docs/usage/elements/field.md index fe8e9756fc..415b4d170e 100644 --- a/docs/usage/elements/field.md +++ b/docs/usage/elements/field.md @@ -8,6 +8,7 @@ Currently the following fields are supported: - XE - INDEX - FILENAME +- REF ``` php addField('XE', array(), array(), $fieldText); //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', + ]); ``` diff --git a/src/PhpWord/Element/Field.php b/src/PhpWord/Element/Field.php index b371bb80d7..ed4225f3f1 100644 --- a/src/PhpWord/Element/Field.php +++ b/src/PhpWord/Element/Field.php @@ -91,6 +91,10 @@ class Field extends AbstractElement ], 'options' => ['Path', 'PreserveFormat'], ], + 'REF' => array( + 'properties' => array('name' => ''), + 'options' => array('f', 'h', 'n', 'p', 'r', 't', 'w'), + ), ]; /** diff --git a/src/PhpWord/Writer/Word2007/Element/Field.php b/src/PhpWord/Writer/Word2007/Element/Field.php index 4d7c2a0b46..f393883b1b 100644 --- a/src/PhpWord/Writer/Word2007/Element/Field.php +++ b/src/PhpWord/Writer/Word2007/Element/Field.php @@ -226,4 +226,106 @@ private function buildPropertiesAndOptions(\PhpOffice\PhpWord\Element\Field $ele return $propertiesAndOptions; } + + /** + * Writes a REF field + * + * @param \PhpOffice\PhpWord\Element\Field $element + */ + protected function writeRef(\PhpOffice\PhpWord\Element\Field $element) + { + $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($optionKey, $optionValue) + { + 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 ''; + } + } } diff --git a/tests/PhpWord/Writer/Word2007/Element/FieldTest.php b/tests/PhpWord/Writer/Word2007/Element/FieldTest.php new file mode 100644 index 0000000000..cf8e0fc834 --- /dev/null +++ b/tests/PhpWord/Writer/Word2007/Element/FieldTest.php @@ -0,0 +1,62 @@ +addSection(); + $section->addField( + 'REF', + array( + 'name' => 'my-bookmark', + ), + array( + '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'; + + $this->assertTrue($doc->elementExists($refFieldPath)); + + $bookMarkElement = $doc->getElement($refFieldPath); + + $this->assertNotNull($bookMarkElement); + + $this->assertEquals(' REF my-bookmark \r \h ', $bookMarkElement->textContent); + + $bookmarkPath = '/w:document/w:body/w:bookmarkStart'; + + $this->assertTrue($doc->elementExists($bookmarkPath)); + $this->assertEquals('my-bookmark', $doc->getElementAttribute("$bookmarkPath", 'w:name')); + } +}