diff --git a/CHANGELOG.md b/CHANGELOG.md index 22f22dd9..6f9bf239 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ This release added form fields (textinput, checkbox, and dropdown), drawing shap - FormField: Ability to add textinput, checkbox, and dropdown form elements - @ivanlanin GH-266 - Setting: Ability to define document protection (readOnly, comments, trackedChanges, forms) - @ivanlanin - Setting: Ability to remove [Compatibility Mode] text in the MS Word title bar - @ivanlanin +- SDT: Ability to add structured document tag elements (comboBox, dropDownList, date) - @ivanlanin ### Bugfixes diff --git a/samples/Sample_34_SDT.php b/samples/Sample_34_SDT.php new file mode 100644 index 00000000..241dee2a --- /dev/null +++ b/samples/Sample_34_SDT.php @@ -0,0 +1,26 @@ +addSection(); + +$textrun = $section->addTextRun(); +$textrun->addText('Combobox: '); +$textrun->addSDT('comboBox')->setListItems(array('1' => 'Choice 1', '2' => 'Choice 2')); + +$textrun = $section->addTextRun(); +$textrun->addText('Date: '); +$textrun->addSDT('date'); + +$textrun = $section->addTextRun(); +$textrun->addText('Drop down list: '); +$textrun->addSDT('dropDownList')->setListItems(array('1' => 'Choice 1', '2' => 'Choice 2')); + +// Save file +echo write($phpWord, basename(__FILE__, '.php'), $writers); +if (!CLI) { + include_once 'Sample_Footer.php'; +} diff --git a/src/PhpWord/Element/AbstractContainer.php b/src/PhpWord/Element/AbstractContainer.php index 3ec11390..b934b2d8 100644 --- a/src/PhpWord/Element/AbstractContainer.php +++ b/src/PhpWord/Element/AbstractContainer.php @@ -43,6 +43,7 @@ namespace PhpOffice\PhpWord\Element; * @method Shape addObject(string $type, mixed $style = null) * @method Chart addChart(string $type, array $categories, array $values, array $style = null) * @method FormField addFormField(string $type, mixed $fStyle = null, mixed $pStyle = null) + * @method SDT addSDT(string $type) * * @since 0.10.0 */ @@ -79,7 +80,7 @@ abstract class AbstractContainer extends AbstractElement $elements = array('Text', 'TextRun', 'Link', 'PreserveText', 'TextBreak', 'ListItem', 'ListItemRun', 'Table', 'Image', 'Object', 'Footnote', 'Endnote', 'CheckBox', 'TextBox', 'Field', 'Line', 'Shape', - 'Title', 'TOC', 'PageBreak', 'Chart', 'FormField'); + 'Title', 'TOC', 'PageBreak', 'Chart', 'FormField', 'SDT'); $functions = array(); for ($i = 0; $i < count($elements); $i++) { $functions[$i] = 'add' . $elements[$i]; @@ -192,6 +193,7 @@ abstract class AbstractContainer extends AbstractElement 'Line' => $allContainers, 'Shape' => $allContainers, 'FormField' => $allContainers, + 'SDT' => $allContainers, 'TextRun' => array('Section', 'Header', 'Footer', 'Cell', 'TextBox'), 'ListItem' => array('Section', 'Header', 'Footer', 'Cell', 'TextBox'), 'ListItemRun' => array('Section', 'Header', 'Footer', 'Cell', 'TextBox'), diff --git a/src/PhpWord/Element/SDT.php b/src/PhpWord/Element/SDT.php new file mode 100644 index 00000000..477c50f3 --- /dev/null +++ b/src/PhpWord/Element/SDT.php @@ -0,0 +1,130 @@ +setType($type); + } + + /** + * Get type + * + * @return string + */ + public function getType() + { + return $this->type; + } + + /** + * Set type + * + * @param string $value + * @return self + */ + public function setType($value) + { + $enum = array('comboBox', 'dropDownList', 'date'); + $this->type = $this->setEnumVal($value, $enum, $this->type); + + return $this; + } + + /** + * Get value + * + * @return string|bool|int + */ + public function getValue() + { + return $this->value; + } + + /** + * Set value + * + * @param string|bool|int $value + * @return self + */ + public function setValue($value) + { + $this->value = $value; + + return $this; + } + + /** + * Get listItems + * + * @return array + */ + public function getListItems() + { + return $this->listItems; + } + + /** + * Set listItems + * + * @param array $value + * @return self + */ + public function setListItems($value) + { + $this->listItems = $value; + + return $this; + } +} diff --git a/src/PhpWord/Writer/Word2007/Element/SDT.php b/src/PhpWord/Writer/Word2007/Element/SDT.php new file mode 100644 index 00000000..94578e16 --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/SDT.php @@ -0,0 +1,110 @@ +getXmlWriter(); + $element = $this->getElement(); + if (!$element instanceof SDTElement) { + return; + } + $type = $element->getType(); + $writeFormField = "write{$type}"; + + $this->startElementP(); + + $xmlWriter->startElement('w:sdt'); + + // Properties + $xmlWriter->startElement('w:sdtPr'); + $xmlWriter->writeElementBlock('w:id', 'w:val', rand(100000000, 999999999)); + $xmlWriter->writeElementBlock('w:lock', 'w:val', 'sdtLocked'); + $this->$writeFormField($xmlWriter, $element); + $xmlWriter->endElement(); // w:sdtPr + + // Content + $xmlWriter->startElement('w:sdtContent'); + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:t'); + $xmlWriter->writeRaw('Pick value'); + $xmlWriter->endElement(); // w:t + $xmlWriter->endElement(); // w:r + $xmlWriter->endElement(); // w:sdtContent + + $xmlWriter->endElement(); // w:sdt + + $this->endElementP(); // w:p + } + + /** + * Write combo box + * + * @link http://www.datypic.com/sc/ooxml/t-w_CT_SdtComboBox.html + */ + private function writeComboBox(XMLWriter $xmlWriter, SDTElement $element) + { + $type = $element->getType(); + $listItems = $element->getListItems(); + + $xmlWriter->startElement("w:{$type}"); + foreach ($listItems as $key => $val) { + $xmlWriter->writeElementBlock('w:listItem', array('w:value' => $key, 'w:displayText' => $val)); + } + $xmlWriter->endElement(); // w:{$type} + } + + /** + * Write drop down list + * + * @link http://www.datypic.com/sc/ooxml/t-w_CT_SdtDropDownList.html + */ + private function writeDropDownList(XMLWriter $xmlWriter, SDTElement $element) + { + $this->writecomboBox($xmlWriter, $element); + } + + /** + * Write date + * + * @link http://www.datypic.com/sc/ooxml/t-w_CT_SdtDate.html + */ + private function writeDate(XMLWriter $xmlWriter, SDTElement $element) + { + $xmlWriter->startElement("w:date"); + $xmlWriter->writeElementBlock('w:dateFormat', 'w:val', 'd/M/yyyy'); + $xmlWriter->writeElementBlock('w:lid', 'w:val', 'en-US'); + $xmlWriter->writeElementBlock('w:storeMappedDataAs', 'w:val', 'dateTime'); + $xmlWriter->writeElementBlock('w:calendar', 'w:val', 'gregorian'); + $xmlWriter->endElement(); // w:date + } +} diff --git a/tests/PhpWord/Tests/Writer/Word2007/ElementTest.php b/tests/PhpWord/Tests/Writer/Word2007/ElementTest.php index 6c10f3a5..92a74c15 100644 --- a/tests/PhpWord/Tests/Writer/Word2007/ElementTest.php +++ b/tests/PhpWord/Tests/Writer/Word2007/ElementTest.php @@ -41,7 +41,7 @@ class ElementTest extends \PHPUnit_Framework_TestCase $elements = array( 'CheckBox', 'Container', 'Footnote', 'Image', 'Link', 'ListItem', 'ListItemRun', 'Object', 'PreserveText', 'Table', 'Text', 'TextBox', 'TextBreak', 'Title', 'TOC', - 'Field', 'Line', 'Shape', 'Chart' + 'Field', 'Line', 'Shape', 'Chart', 'FormField', 'SDT' ); foreach ($elements as $element) { $objectClass = 'PhpOffice\\PhpWord\\Writer\\Word2007\\Element\\' . $element; @@ -196,4 +196,24 @@ class ElementTest extends \PHPUnit_Framework_TestCase $this->assertTrue($doc->elementExists($path . '/w:checkBox')); $this->assertTrue($doc->elementExists($path . '/w:ddList')); } + + /** + * Test SDT elements + */ + public function testSDTElements() + { + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + + $section->addSDT('comboBox'); + $section->addSDT('dropDownList'); + $section->addSDT('date'); + + $doc = TestHelperDOCX::getDocument($phpWord); + + $path = "/w:document/w:body/w:p/w:sdt/w:sdtPr"; + $this->assertTrue($doc->elementExists($path . '/w:comboBox')); + $this->assertTrue($doc->elementExists($path . '/w:dropDownList')); + $this->assertTrue($doc->elementExists($path . '/w:date')); + } }