Add support for MACROBUTTON Field (#1021)

* add functionality to use MACROBUTTON as Field, use Styles for Field, add noProof to Font Style
* code review
* refactoring + fixes + unit tests
This commit is contained in:
Lenz Weber 2018-02-27 23:27:18 +01:00 committed by troosan
parent f3c73f333a
commit 7fe32e6ac1
7 changed files with 191 additions and 1 deletions

View File

@ -13,6 +13,7 @@ v0.15.0 (?? ??? 2018)
- Add support for fixed Table Layout @aoloe @ekopach @troosan #841 #1276
- Add support for Cell Spacing @dox07 @troosan #1040
- Add parsing of formatting inside lists @atomicalnet @troosan #594
- Add support for MACROBUTTON field @phryneas @troosan #1021
### Fixed
- Fix reading of docx default style - @troosan #1238

View File

@ -20,6 +20,7 @@ $section->addField('PAGE', array('format' => 'Arabic'));
$section->addText('Number of pages field:');
$section->addField('NUMPAGES', array('numformat' => '0,00', 'format' => 'Arabic'), array('PreserveFormat'));
$section->addTextBreak();
$textrun = $section->addTextRun();
$textrun->addText('An index field is ');
@ -43,6 +44,19 @@ $textrun = $section->addTextRun(array('alignment' => \PhpOffice\PhpWord\SimpleTy
$textrun->addText('This is the date of lunar calendar ');
$textrun->addField('DATE', array('dateformat' => 'd-M-yyyy H:mm:ss'), array('PreserveFormat', 'LunarCalendar'));
$textrun->addText(' written in a textrun.');
$section->addTextBreak();
$macroText = new TextRun();
$macroText->addText('Double click', array('bold' => true));
$macroText->addText(' to ');
$macroText->addText('zoom to 100%', array('italic' => true));
$section->addText('A macro button with styled text:');
$section->addField('MACROBUTTON', array('macroname' => 'Zoom100'), array(), $macroText);
$section->addTextBreak();
$section->addText('A macro button with simple text:');
$section->addField('MACROBUTTON', array('macroname' => 'Zoom100'), array(), 'double click to zoom');
// Save file
echo write($phpWord, basename(__FILE__, '.php'), $writers);

View File

@ -17,6 +17,8 @@
namespace PhpOffice\PhpWord\Element;
use PhpOffice\PhpWord\Style\Font;
/**
* Field element
*
@ -54,6 +56,9 @@ class Field extends AbstractElement
),
'options' => array('PreserveFormat', 'LunarCalendar', 'SakaEraCalendar', 'LastUsedFormat'),
),
'MACROBUTTON' => array(
'properties' => array('macroname' => ''),
),
'XE' => array(
'properties' => array(),
'options' => array('Bold', 'Italic'),
@ -92,6 +97,13 @@ class Field extends AbstractElement
*/
protected $options = array();
/**
* Font style
*
* @var \PhpOffice\PhpWord\Style\Font
*/
protected $fontStyle;
/**
* Create a new Field Element
*
@ -203,6 +215,46 @@ class Field extends AbstractElement
return $this->options;
}
/**
* Set Text style
*
* @param \PhpOffice\PhpWord\Style\Font $style
* @return \PhpOffice\PhpWord\Style\Font
*/
public function setFontStyle($style = null)
{
if (!$style instanceof Font) {
throw new \InvalidArgumentException('font style must be of type Font');
}
if ($style->isNoProof()) {
$this->fontStyle = $style;
} else {
// make a copy of the font so the original is not altered
$this->fontStyle = clone $style;
$this->fontStyle->setNoProof(true);
}
return $this->fontStyle;
}
/**
* Get Text style
*
* @return \PhpOffice\PhpWord\Style\Font
*/
public function getFontStyle()
{
if ($this->fontStyle == null) {
$font = new Font();
$font->setNoProof(true);
return $font;
}
return $this->fontStyle;
}
/**
* Set Field text
*

View File

@ -236,6 +236,14 @@ class Font extends AbstractStyle
*/
private $rtl = false;
/**
* noProof (disables AutoCorrect)
*
* @var bool
* http://www.datypic.com/sc/ooxml/e-w_noProof-1.html
*/
private $noProof = false;
/**
* Languages
* @var \PhpOffice\PhpWord\Style\Language
@ -706,6 +714,29 @@ class Font extends AbstractStyle
return $this;
}
/**
* Get noProof (disables autocorrect)
*
* @return bool
*/
public function isNoProof()
{
return $this->noProof;
}
/**
* Set noProof (disables autocorrect)
*
* @param bool $value
* @return $this
*/
public function setNoProof($value = false)
{
$this->noProof = $value;
return $this;
}
/**
* Get line height
*

View File

@ -29,12 +29,22 @@ class Field extends Text
*/
public function write()
{
$xmlWriter = $this->getXmlWriter();
$element = $this->getElement();
if (!$element instanceof \PhpOffice\PhpWord\Element\Field) {
return;
}
$methodName = 'write' . ucfirst(strtolower($element->getType()));
if (method_exists($this, $methodName)) {
$this->$methodName($element);
} else {
$this->writeDefault($element);
}
}
private function writeDefault(\PhpOffice\PhpWord\Element\Field $element)
{
$xmlWriter = $this->getXmlWriter();
$this->startElementP();
$xmlWriter->startElement('w:r');
@ -104,6 +114,51 @@ class Field extends Text
$this->endElementP(); // w:p
}
/**
* Writes a macrobutton field
*
* //TODO A lot of code duplication with general method, should maybe be refactored
* @param \PhpOffice\PhpWord\Element\Field $element
*/
protected function writeMacrobutton(\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() . ' ' . $this->buildPropertiesAndOptions($element);
if (is_string($element->getText())) {
$instruction .= $element->getText() . ' ';
}
$xmlWriter->startElement('w:r');
$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:fldChar');
$xmlWriter->writeAttribute('w:fldCharType', 'end');
$xmlWriter->endElement(); // w:fldChar
$xmlWriter->endElement(); // w:r
$this->endElementP(); // w:p
}
private function buildPropertiesAndOptions(\PhpOffice\PhpWord\Element\Field $element)
{
$propertiesAndOptions = '';
@ -119,6 +174,9 @@ class Field extends Text
case 'dateformat':
$propertiesAndOptions .= '\@ "' . $propval . '" ';
break;
case 'macroname':
$propertiesAndOptions .= $propval . ' ';
break;
}
}

View File

@ -135,6 +135,9 @@ class Font extends AbstractStyle
$xmlWriter->writeElementIf($style->getSpacing() !== null, 'w:spacing', 'w:val', $style->getSpacing());
$xmlWriter->writeElementIf($style->getKerning() !== null, 'w:kern', 'w:val', $style->getKerning() * 2);
// noProof
$xmlWriter->writeElementIf($style->isNoProof() !== false, 'w:noProof');
// Background-Color
$shading = $style->getShading();
if (!is_null($shading)) {

View File

@ -322,6 +322,37 @@ class ElementTest extends \PHPUnit\Framework\TestCase
$this->assertEquals('"\\b \\i ', $doc->getElement($element)->textContent);
}
/**
* Test writing the macrobutton field
*/
public function testMacroButtonField()
{
$phpWord = new PhpWord();
$section = $phpWord->addSection();
$macroText = new TextRun();
$macroText->addText('Double click', array('bold' => true));
$macroText->addText(' to ');
$macroText->addText('zoom to 100%', array('italic' => true));
$section->addField('MACROBUTTON', array('macroname' => 'Zoom100'), array(), $macroText);
$section->addField('MACROBUTTON', array('macroname' => 'Zoom100'), array(), 'double click to zoom');
$doc = TestHelperDOCX::getDocument($phpWord);
$element = '/w:document/w:body/w:p[1]/w:r[2]/w:instrText';
$this->assertTrue($doc->elementExists($element));
$this->assertEquals(' MACROBUTTON Zoom100 ', $doc->getElement($element)->textContent);
$element = '/w:document/w:body/w:p[1]/w:r[3]/';
$this->assertTrue($doc->elementExists($element . 'w:t'));
$this->assertEquals('Double click', $doc->getElement($element . 'w:t')->textContent);
$this->assertTrue($doc->elementExists($element . 'w:rPr/w:b'));
$element = '/w:document/w:body/w:p[2]/w:r[2]/w:instrText';
$this->assertTrue($doc->elementExists($element));
$this->assertEquals(' MACROBUTTON Zoom100 double click to zoom ', $doc->getElement($element)->textContent);
}
/**
* Test form fields
*/