From cd547927eaa6385cf1d2471d642e2d60677c193a Mon Sep 17 00:00:00 2001 From: Ivan Lanin Date: Fri, 20 Jun 2014 22:24:59 +0700 Subject: [PATCH 1/2] New structured document tag (SDT) element --- samples/Sample_34_SDT.php | 17 +++ src/PhpWord/Element/AbstractContainer.php | 4 +- src/PhpWord/Element/SDT.php | 130 ++++++++++++++++++ src/PhpWord/Writer/Word2007/Element/SDT.php | 71 ++++++++++ .../Tests/Writer/Word2007/ElementTest.php | 2 +- 5 files changed, 222 insertions(+), 2 deletions(-) create mode 100644 samples/Sample_34_SDT.php create mode 100644 src/PhpWord/Element/SDT.php create mode 100644 src/PhpWord/Writer/Word2007/Element/SDT.php diff --git a/samples/Sample_34_SDT.php b/samples/Sample_34_SDT.php new file mode 100644 index 00000000..fc1e7de6 --- /dev/null +++ b/samples/Sample_34_SDT.php @@ -0,0 +1,17 @@ +getProtection()->setEditing('forms'); + +$section = $phpWord->addSection(); + +$section->addSDT('comboBox')->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..afde4270 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]; @@ -205,6 +206,7 @@ abstract class AbstractContainer extends AbstractElement 'TOC' => array('Section'), 'PageBreak' => array('Section'), 'Chart' => array('Section'), + 'SDT' => array('Section'), ); // Special condition, e.g. preservetext can only exists in cell when // the cell is located in header or footer 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..d25eaf98 --- /dev/null +++ b/src/PhpWord/Writer/Word2007/Element/SDT.php @@ -0,0 +1,71 @@ +getXmlWriter(); + $element = $this->getElement(); + if (!$element instanceof SDTElement) { + return; + } + $type = $element->getType(); + $listItems = $element->getListItems(); + + $this->startElementP(); + + $xmlWriter->startElement('w:sdt'); + + $xmlWriter->startElement('w:sdtPr'); + $xmlWriter->writeElementBlock('w:id', 'w:val', rand(100000000, 999999999)); + $xmlWriter->writeElementBlock('w:lock', 'w:val', 'sdtLocked'); + + $xmlWriter->startElement('w:placeholder'); + $xmlWriter->writeElementBlock('w:docPart', 'w:val', 'string'); + $xmlWriter->endElement(); // w:placeholder + + $xmlWriter->startElement("w:{$type}"); + foreach ($listItems as $key => $val) { + $xmlWriter->writeElementBlock('w:listItem', array('w:value' => $key, 'w:displayText' => $val)); + } + $xmlWriter->endElement(); // w:{$type} + + $xmlWriter->endElement(); // w:sdtPr + + $xmlWriter->startElement('w:sdtContent'); + $xmlWriter->endElement(); // w:sdtContent + + $xmlWriter->endElement(); // w:sdt + + $this->endElementP(); // w:p + } +} diff --git a/tests/PhpWord/Tests/Writer/Word2007/ElementTest.php b/tests/PhpWord/Tests/Writer/Word2007/ElementTest.php index 6c10f3a5..752415a1 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; From b5a63c5b55a77e9d75dc52439f9b60587ac76a20 Mon Sep 17 00:00:00 2001 From: Ivan Lanin Date: Sat, 28 Jun 2014 11:47:04 +0700 Subject: [PATCH 2/2] Elaborate SDT elements --- CHANGELOG.md | 1 + samples/Sample_34_SDT.php | 13 +++- src/PhpWord/Element/AbstractContainer.php | 2 +- src/PhpWord/Writer/Word2007/Element/SDT.php | 63 +++++++++++++++---- .../Tests/Writer/Word2007/ElementTest.php | 20 ++++++ 5 files changed, 84 insertions(+), 15 deletions(-) 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 index fc1e7de6..241dee2a 100644 --- a/samples/Sample_34_SDT.php +++ b/samples/Sample_34_SDT.php @@ -4,11 +4,20 @@ include_once 'Sample_Header.php'; // New Word document echo date('H:i:s'), " Create new PhpWord object", EOL; $phpWord = new \PhpOffice\PhpWord\PhpWord(); -$phpWord->getProtection()->setEditing('forms'); $section = $phpWord->addSection(); -$section->addSDT('comboBox')->setListItems(array('1' => 'Choice 1', '2' => 'Choice 2')); +$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); diff --git a/src/PhpWord/Element/AbstractContainer.php b/src/PhpWord/Element/AbstractContainer.php index afde4270..b934b2d8 100644 --- a/src/PhpWord/Element/AbstractContainer.php +++ b/src/PhpWord/Element/AbstractContainer.php @@ -193,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'), @@ -206,7 +207,6 @@ abstract class AbstractContainer extends AbstractElement 'TOC' => array('Section'), 'PageBreak' => array('Section'), 'Chart' => array('Section'), - 'SDT' => array('Section'), ); // Special condition, e.g. preservetext can only exists in cell when // the cell is located in header or footer diff --git a/src/PhpWord/Writer/Word2007/Element/SDT.php b/src/PhpWord/Writer/Word2007/Element/SDT.php index d25eaf98..94578e16 100644 --- a/src/PhpWord/Writer/Word2007/Element/SDT.php +++ b/src/PhpWord/Writer/Word2007/Element/SDT.php @@ -39,33 +39,72 @@ class SDT extends Text return; } $type = $element->getType(); - $listItems = $element->getListItems(); + $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'); - - $xmlWriter->startElement('w:placeholder'); - $xmlWriter->writeElementBlock('w:docPart', 'w:val', 'string'); - $xmlWriter->endElement(); // w:placeholder - - $xmlWriter->startElement("w:{$type}"); - foreach ($listItems as $key => $val) { - $xmlWriter->writeElementBlock('w:listItem', array('w:value' => $key, 'w:displayText' => $val)); - } - $xmlWriter->endElement(); // w:{$type} - + $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 752415a1..92a74c15 100644 --- a/tests/PhpWord/Tests/Writer/Word2007/ElementTest.php +++ b/tests/PhpWord/Tests/Writer/Word2007/ElementTest.php @@ -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')); + } }