ODT Changes
Implement a number of features implemented in PhpWord,
but not yet supported in PhpWord ODT Writer.
1. Add default file to tests/PhpWord/_includes/XmlDocument.php to make it
considerably easier to test ODT changes (and Word2007 changes involving
files other that document.xml).
2. Page break before each section.
3. Page numbering start.
4. Font style for Headings.
5. Alignment for images.
6. Paragraph style for TextRun.
7. "Hide grammatical errors" for whole document.
8. Page layout for each section.
9. For each page layout, support user-specified page width, page height,
orientation, margin top, margin bottom, margin left, margin right.
10. Page header and footer.
11. Named colors.
12. NoProof font style.
13. Paragraph Style - spaceBefore, spaceAfter, lineHeight, pageBreakBefore,
indentation, text alignment.
14. Tab stops.
15. Basic support for some Fields (DATE, PAGE, NUMPAGES).
16. Link had an error in how it was handling internal links (needs leading #).
17. In addition to tests for all the above, added some tests for Tables.
Item 11 above needs 1 module from Pull Request 1775, which is targeted
for v0.18.0 but not yet merged, so the relevant module is also here.
Item 15 above needs 1 module from Pull Request 1774, which is targeted
for v0.18.0 but not yet merged, so the relevant module is also here.
Testing change from Pull Request 1771 is included here, but was
merged after my fork.
This commit is contained in:
parent
733f845f8f
commit
e24b2e1ba7
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpWord\Element;
|
namespace PhpOffice\PhpWord\Element;
|
||||||
|
|
||||||
|
use PhpOffice\PhpWord\Style\Font;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Field element
|
* Field element
|
||||||
*
|
*
|
||||||
|
|
@ -115,10 +117,42 @@ class Field extends AbstractElement
|
||||||
/**
|
/**
|
||||||
* Font style
|
* Font style
|
||||||
*
|
*
|
||||||
* @var \PhpOffice\PhpWord\Style\Font
|
* @var string|\PhpOffice\PhpWord\Style\Font
|
||||||
*/
|
*/
|
||||||
protected $fontStyle;
|
protected $fontStyle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Font style
|
||||||
|
*
|
||||||
|
* @param string|array|\PhpOffice\PhpWord\Style\Font $style
|
||||||
|
* @return string|\PhpOffice\PhpWord\Style\Font
|
||||||
|
*/
|
||||||
|
public function setFontStyle($style = null)
|
||||||
|
{
|
||||||
|
if ($style instanceof Font) {
|
||||||
|
$this->fontStyle = $style;
|
||||||
|
} elseif (is_array($style)) {
|
||||||
|
$this->fontStyle = new Font('text');
|
||||||
|
$this->fontStyle->setStyleByArray($style);
|
||||||
|
} elseif (null === $style) {
|
||||||
|
$this->fontStyle = null;
|
||||||
|
} else {
|
||||||
|
$this->fontStyle = $style;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->fontStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Font style
|
||||||
|
*
|
||||||
|
* @return string|\PhpOffice\PhpWord\Style\Font
|
||||||
|
*/
|
||||||
|
public function getFontStyle()
|
||||||
|
{
|
||||||
|
return $this->fontStyle;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new Field Element
|
* Create a new Field Element
|
||||||
*
|
*
|
||||||
|
|
@ -126,13 +160,15 @@ class Field extends AbstractElement
|
||||||
* @param array $properties
|
* @param array $properties
|
||||||
* @param array $options
|
* @param array $options
|
||||||
* @param TextRun|string|null $text
|
* @param TextRun|string|null $text
|
||||||
|
* @param string|array|\PhpOffice\PhpWord\Style\Font $fontStyle
|
||||||
*/
|
*/
|
||||||
public function __construct($type = null, $properties = array(), $options = array(), $text = null)
|
public function __construct($type = null, $properties = array(), $options = array(), $text = null, $fontStyle = null)
|
||||||
{
|
{
|
||||||
$this->setType($type);
|
$this->setType($type);
|
||||||
$this->setProperties($properties);
|
$this->setProperties($properties);
|
||||||
$this->setOptions($options);
|
$this->setOptions($options);
|
||||||
$this->setText($text);
|
$this->setText($text);
|
||||||
|
$this->setFontStyle($fontStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -272,6 +272,50 @@ class Converter
|
||||||
return round($angle / self::DEGREE_TO_ANGLE);
|
return round($angle / self::DEGREE_TO_ANGLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert colorname as string to RGB
|
||||||
|
*
|
||||||
|
* @param string $value color name
|
||||||
|
* @return string color as hex RGB string, or original value if unknown
|
||||||
|
*/
|
||||||
|
public static function stringToRgb($value)
|
||||||
|
{
|
||||||
|
switch ($value) {
|
||||||
|
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_YELLOW:
|
||||||
|
return 'FFFF00';
|
||||||
|
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_LIGHTGREEN:
|
||||||
|
return '90EE90';
|
||||||
|
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_CYAN:
|
||||||
|
return '00FFFF';
|
||||||
|
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_MAGENTA:
|
||||||
|
return 'FF00FF';
|
||||||
|
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_BLUE:
|
||||||
|
return '0000FF';
|
||||||
|
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_RED:
|
||||||
|
return 'FF0000';
|
||||||
|
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_DARKBLUE:
|
||||||
|
return '00008B';
|
||||||
|
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_DARKCYAN:
|
||||||
|
return '008B8B';
|
||||||
|
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_DARKGREEN:
|
||||||
|
return '006400';
|
||||||
|
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_DARKMAGENTA:
|
||||||
|
return '8B008B';
|
||||||
|
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_DARKRED:
|
||||||
|
return '8B0000';
|
||||||
|
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_DARKYELLOW:
|
||||||
|
return '8B8B00';
|
||||||
|
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_DARKGRAY:
|
||||||
|
return 'A9A9A9';
|
||||||
|
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_LIGHTGRAY:
|
||||||
|
return 'D3D3D3';
|
||||||
|
case \PhpOffice\PhpWord\Style\Font::FGCOLOR_BLACK:
|
||||||
|
return '000000';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert HTML hexadecimal to RGB
|
* Convert HTML hexadecimal to RGB
|
||||||
*
|
*
|
||||||
|
|
@ -282,6 +326,8 @@ class Converter
|
||||||
{
|
{
|
||||||
if ($value[0] == '#') {
|
if ($value[0] == '#') {
|
||||||
$value = substr($value, 1);
|
$value = substr($value, 1);
|
||||||
|
} else {
|
||||||
|
$value = self::stringToRgb($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen($value) == 6) {
|
if (strlen($value) == 6) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
<?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
|
||||||
|
* @copyright 2010-2018 PHPWord contributors
|
||||||
|
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
|
||||||
|
*/
|
||||||
|
// Not fully implemented
|
||||||
|
// - supports only PAGE and NUMPAGES
|
||||||
|
// - supports only default formats and options
|
||||||
|
// - supports style only if specified by name
|
||||||
|
// - spaces before and after field may be dropped
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpWord\Writer\ODText\Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Field element writer
|
||||||
|
*
|
||||||
|
* @since 0.11.0
|
||||||
|
*/
|
||||||
|
class Field extends Text
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Write field element.
|
||||||
|
*/
|
||||||
|
public function write()
|
||||||
|
{
|
||||||
|
$element = $this->getElement();
|
||||||
|
if (!$element instanceof \PhpOffice\PhpWord\Element\Field) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$type = strtolower($element->getType());
|
||||||
|
switch ($type) {
|
||||||
|
case 'date': // Owen 2020-01-02
|
||||||
|
case 'page':
|
||||||
|
case 'numpages':
|
||||||
|
$this->writeDefault($element, $type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function writeDefault(\PhpOffice\PhpWord\Element\Field $element, $type)
|
||||||
|
{
|
||||||
|
$xmlWriter = $this->getXmlWriter();
|
||||||
|
|
||||||
|
$xmlWriter->startElement('text:span');
|
||||||
|
if (method_exists($element, 'getFontStyle')) {
|
||||||
|
$fstyle = $element->getFontStyle();
|
||||||
|
if (is_string($fstyle)) {
|
||||||
|
$xmlWriter->writeAttribute('text:style-name', $fstyle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch ($type) {
|
||||||
|
case 'date': // Owen 2019-01-02
|
||||||
|
$xmlWriter->startElement('text:date');
|
||||||
|
$xmlWriter->writeAttribute('text:fixed', 'false');
|
||||||
|
$xmlWriter->endElement();
|
||||||
|
break;
|
||||||
|
case 'page':
|
||||||
|
$xmlWriter->startElement('text:page-number');
|
||||||
|
$xmlWriter->writeAttribute('text:fixed', 'false');
|
||||||
|
$xmlWriter->endElement();
|
||||||
|
break;
|
||||||
|
case 'numpages':
|
||||||
|
$xmlWriter->startElement('text:page-count');
|
||||||
|
$xmlWriter->endElement();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$xmlWriter->endElement(); // text:span
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -44,7 +44,7 @@ class Image extends AbstractElement
|
||||||
$height = Converter::pixelToCm($style->getHeight());
|
$height = Converter::pixelToCm($style->getHeight());
|
||||||
|
|
||||||
$xmlWriter->startElement('text:p');
|
$xmlWriter->startElement('text:p');
|
||||||
$xmlWriter->writeAttribute('text:style-name', 'Standard');
|
$xmlWriter->writeAttribute('text:style-name', 'IM' . $mediaIndex);
|
||||||
|
|
||||||
$xmlWriter->startElement('draw:frame');
|
$xmlWriter->startElement('draw:frame');
|
||||||
$xmlWriter->writeAttribute('draw:style-name', 'fr' . $mediaIndex);
|
$xmlWriter->writeAttribute('draw:style-name', 'fr' . $mediaIndex);
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ class Link extends AbstractElement
|
||||||
|
|
||||||
$xmlWriter->startElement('text:a');
|
$xmlWriter->startElement('text:a');
|
||||||
$xmlWriter->writeAttribute('xlink:type', 'simple');
|
$xmlWriter->writeAttribute('xlink:type', 'simple');
|
||||||
$xmlWriter->writeAttribute('xlink:href', $element->getSource());
|
$xmlWriter->writeAttribute('xlink:href', ($element->isInternal() ? '#' : '') . $element->getSource());
|
||||||
$this->writeText($element->getText());
|
$this->writeText($element->getText());
|
||||||
$xmlWriter->endElement(); // text:a
|
$xmlWriter->endElement(); // text:a
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ class PageBreak extends AbstractElement
|
||||||
$xmlWriter = $this->getXmlWriter();
|
$xmlWriter = $this->getXmlWriter();
|
||||||
|
|
||||||
$xmlWriter->startElement('text:p');
|
$xmlWriter->startElement('text:p');
|
||||||
$xmlWriter->writeAttribute('text:style-name', 'P1');
|
$xmlWriter->writeAttribute('text:style-name', 'PB');
|
||||||
$xmlWriter->endElement();
|
$xmlWriter->endElement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,18 +59,26 @@ class Text extends AbstractElement
|
||||||
} else {
|
} else {
|
||||||
if (empty($fontStyle)) {
|
if (empty($fontStyle)) {
|
||||||
if (empty($paragraphStyle)) {
|
if (empty($paragraphStyle)) {
|
||||||
$xmlWriter->writeAttribute('text:style-name', 'P1');
|
if (!$this->withoutP) {
|
||||||
|
$xmlWriter->writeAttribute('text:style-name', 'Normal');
|
||||||
|
}
|
||||||
} elseif (is_string($paragraphStyle)) {
|
} elseif (is_string($paragraphStyle)) {
|
||||||
$xmlWriter->writeAttribute('text:style-name', $paragraphStyle);
|
if (!$this->withoutP) {
|
||||||
|
$xmlWriter->writeAttribute('text:style-name', $paragraphStyle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$this->writeChangeInsertion(true, $element->getTrackChange());
|
$this->writeChangeInsertion(true, $element->getTrackChange());
|
||||||
$this->writeText($element->getText());
|
$this->replaceTabs($element->getText(), $xmlWriter);
|
||||||
$this->writeChangeInsertion(false, $element->getTrackChange());
|
$this->writeChangeInsertion(false, $element->getTrackChange());
|
||||||
} else {
|
} else {
|
||||||
if (empty($paragraphStyle)) {
|
if (empty($paragraphStyle)) {
|
||||||
$xmlWriter->writeAttribute('text:style-name', 'Standard');
|
if (!$this->withoutP) {
|
||||||
|
$xmlWriter->writeAttribute('text:style-name', 'Normal');
|
||||||
|
}
|
||||||
} elseif (is_string($paragraphStyle)) {
|
} elseif (is_string($paragraphStyle)) {
|
||||||
$xmlWriter->writeAttribute('text:style-name', $paragraphStyle);
|
if (!$this->withoutP) {
|
||||||
|
$xmlWriter->writeAttribute('text:style-name', $paragraphStyle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// text:span
|
// text:span
|
||||||
$xmlWriter->startElement('text:span');
|
$xmlWriter->startElement('text:span');
|
||||||
|
|
@ -78,7 +86,7 @@ class Text extends AbstractElement
|
||||||
$xmlWriter->writeAttribute('text:style-name', $fontStyle);
|
$xmlWriter->writeAttribute('text:style-name', $fontStyle);
|
||||||
}
|
}
|
||||||
$this->writeChangeInsertion(true, $element->getTrackChange());
|
$this->writeChangeInsertion(true, $element->getTrackChange());
|
||||||
$this->writeText($element->getText());
|
$this->replaceTabs($element->getText(), $xmlWriter);
|
||||||
$this->writeChangeInsertion(false, $element->getTrackChange());
|
$this->writeChangeInsertion(false, $element->getTrackChange());
|
||||||
$xmlWriter->endElement();
|
$xmlWriter->endElement();
|
||||||
}
|
}
|
||||||
|
|
@ -88,6 +96,34 @@ class Text extends AbstractElement
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function replacetabs($text, $xmlWriter)
|
||||||
|
{
|
||||||
|
if (preg_match('/^ +/', $text, $matches)) {
|
||||||
|
$num = strlen($matches[0]);
|
||||||
|
$xmlWriter->startElement('text:s');
|
||||||
|
$xmlWriter->writeAttributeIf($num > 1, 'text:c', "$num");
|
||||||
|
$xmlWriter->endElement();
|
||||||
|
$text = preg_replace('/^ +/', '', $text);
|
||||||
|
}
|
||||||
|
preg_match_all('/([\\s\\S]*?)(\\t| +| ?$)/', $text, $matches, PREG_SET_ORDER);
|
||||||
|
foreach ($matches as $match) {
|
||||||
|
$this->writeText($match[1]);
|
||||||
|
if ($match[2] === '') {
|
||||||
|
break;
|
||||||
|
} elseif ($match[2] === "\t") {
|
||||||
|
$xmlWriter->writeElement('text:tab');
|
||||||
|
} elseif ($match[2] === ' ') {
|
||||||
|
$xmlWriter->writeElement('text:s');
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
$num = strlen($match[2]);
|
||||||
|
$xmlWriter->startElement('text:s');
|
||||||
|
$xmlWriter->writeAttributeIf($num > 1, 'text:c', "$num");
|
||||||
|
$xmlWriter->endElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private function writeChangeInsertion($start = true, TrackChange $trackChange = null)
|
private function writeChangeInsertion($start = true, TrackChange $trackChange = null)
|
||||||
{
|
{
|
||||||
if ($trackChange == null || $trackChange->getChangeType() != TrackChange::INSERTED) {
|
if ($trackChange == null || $trackChange->getChangeType() != TrackChange::INSERTED) {
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ namespace PhpOffice\PhpWord\Writer\ODText\Element;
|
||||||
*
|
*
|
||||||
* @since 0.10.0
|
* @since 0.10.0
|
||||||
*/
|
*/
|
||||||
class TextRun extends AbstractElement
|
class TextRun extends Text
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Write element
|
* Write element
|
||||||
|
|
@ -33,6 +33,11 @@ class TextRun extends AbstractElement
|
||||||
$element = $this->getElement();
|
$element = $this->getElement();
|
||||||
|
|
||||||
$xmlWriter->startElement('text:p');
|
$xmlWriter->startElement('text:p');
|
||||||
|
$pStyle = $element->getParagraphStyle();
|
||||||
|
if (!is_string($pStyle)) {
|
||||||
|
$pStyle = 'Normal';
|
||||||
|
}
|
||||||
|
$xmlWriter->writeAttribute('text:style-name', $pStyle);
|
||||||
|
|
||||||
$containerWriter = new Container($xmlWriter, $element);
|
$containerWriter = new Container($xmlWriter, $element);
|
||||||
$containerWriter->write();
|
$containerWriter->write();
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,23 @@ class Title extends AbstractElement
|
||||||
}
|
}
|
||||||
|
|
||||||
$xmlWriter->startElement('text:h');
|
$xmlWriter->startElement('text:h');
|
||||||
$xmlWriter->writeAttribute('text:outline-level', $element->getDepth());
|
$hdname = 'HD';
|
||||||
|
$sect = $element->getParent();
|
||||||
|
if ($sect instanceof \PhpOffice\PhpWord\Element\Section) {
|
||||||
|
$elems = $sect->getElements();
|
||||||
|
if ($elems[0] === $element) {
|
||||||
|
$hdname = 'HE';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$depth = $element->getDepth();
|
||||||
|
$xmlWriter->writeAttribute('text:style-name', "$hdname$depth");
|
||||||
|
$xmlWriter->writeAttribute('text:outline-level', $depth);
|
||||||
|
$xmlWriter->startElement('text:span');
|
||||||
|
if ($depth > 0) {
|
||||||
|
$xmlWriter->writeAttribute('text:style-name', 'Heading_' . $depth);
|
||||||
|
} else {
|
||||||
|
$xmlWriter->writeAttribute('text:style-name', 'Title');
|
||||||
|
}
|
||||||
$text = $element->getText();
|
$text = $element->getText();
|
||||||
if (is_string($text)) {
|
if (is_string($text)) {
|
||||||
$this->writeText($text);
|
$this->writeText($text);
|
||||||
|
|
@ -44,6 +60,7 @@ class Title extends AbstractElement
|
||||||
$containerWriter = new Container($xmlWriter, $text);
|
$containerWriter = new Container($xmlWriter, $text);
|
||||||
$containerWriter->write();
|
$containerWriter->write();
|
||||||
}
|
}
|
||||||
|
$xmlWriter->endElement(); // text:span
|
||||||
$xmlWriter->endElement(); // text:h
|
$xmlWriter->endElement(); // text:h
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ class Content extends AbstractPart
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private $autoStyles = array('Section' => array(), 'Image' => array(), 'Table' => array());
|
private $autoStyles = array('Section' => array(), 'Image' => array(), 'Table' => array());
|
||||||
|
private $imageParagraphStyles = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write part
|
* Write part
|
||||||
|
|
@ -128,6 +129,9 @@ class Content extends AbstractPart
|
||||||
$xmlWriter->startElement('text:section');
|
$xmlWriter->startElement('text:section');
|
||||||
$xmlWriter->writeAttribute('text:name', $name);
|
$xmlWriter->writeAttribute('text:name', $name);
|
||||||
$xmlWriter->writeAttribute('text:style-name', $name);
|
$xmlWriter->writeAttribute('text:style-name', $name);
|
||||||
|
$xmlWriter->startElement('text:p');
|
||||||
|
$xmlWriter->writeAttribute('text:style-name', 'SB' . $section->getSectionId());
|
||||||
|
$xmlWriter->endElement();
|
||||||
$containerWriter = new Container($xmlWriter, $section);
|
$containerWriter = new Container($xmlWriter, $section);
|
||||||
$containerWriter->write();
|
$containerWriter->write();
|
||||||
$xmlWriter->endElement(); // text:section
|
$xmlWriter->endElement(); // text:section
|
||||||
|
|
@ -174,28 +178,58 @@ class Content extends AbstractPart
|
||||||
{
|
{
|
||||||
$styles = Style::getStyles();
|
$styles = Style::getStyles();
|
||||||
$paragraphStyleCount = 0;
|
$paragraphStyleCount = 0;
|
||||||
if (count($styles) > 0) {
|
|
||||||
foreach ($styles as $style) {
|
$style = new Paragraph();
|
||||||
if ($style->isAuto() === true) {
|
$style->setStyleName('PB');
|
||||||
$styleClass = str_replace('\\Style\\', '\\Writer\\ODText\\Style\\', get_class($style));
|
$style->setAuto();
|
||||||
if (class_exists($styleClass)) {
|
$styleWriter = new ParagraphStyleWriter($xmlWriter, $style);
|
||||||
/** @var \PhpOffice\PhpWord\Writer\ODText\Style\AbstractStyle $styleWriter Type hint */
|
$styleWriter->write();
|
||||||
$styleWriter = new $styleClass($xmlWriter, $style);
|
|
||||||
$styleWriter->write();
|
$sects = $this->getParentWriter()->getPhpWord()->getSections();
|
||||||
}
|
for ($i = 0; $i < count($sects); ++$i) {
|
||||||
if ($style instanceof Paragraph) {
|
$iplus1 = $i + 1;
|
||||||
$paragraphStyleCount++;
|
$style = new Paragraph();
|
||||||
}
|
$style->setStyleName("SB$iplus1");
|
||||||
}
|
$style->setAuto();
|
||||||
}
|
$pnstart = $sects[$i]->getStyle()->getPageNumberingStart();
|
||||||
if ($paragraphStyleCount == 0) {
|
$style->setNumLevel($pnstart);
|
||||||
|
$styleWriter = new ParagraphStyleWriter($xmlWriter, $style);
|
||||||
|
$styleWriter->write();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($styles as $style) {
|
||||||
|
$sty = $style->getStyleName();
|
||||||
|
if (substr($sty, 0, 8) === 'Heading_') {
|
||||||
$style = new Paragraph();
|
$style = new Paragraph();
|
||||||
$style->setStyleName('P1');
|
$style->setStyleName('HD' . substr($sty, 8));
|
||||||
|
$style->setAuto();
|
||||||
|
$styleWriter = new ParagraphStyleWriter($xmlWriter, $style);
|
||||||
|
$styleWriter->write();
|
||||||
|
$style = new Paragraph();
|
||||||
|
$style->setStyleName('HE' . substr($sty, 8));
|
||||||
$style->setAuto();
|
$style->setAuto();
|
||||||
$styleWriter = new ParagraphStyleWriter($xmlWriter, $style);
|
$styleWriter = new ParagraphStyleWriter($xmlWriter, $style);
|
||||||
$styleWriter->write();
|
$styleWriter->write();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach ($styles as $style) {
|
||||||
|
if ($style->isAuto() === true) {
|
||||||
|
$styleClass = str_replace('\\Style\\', '\\Writer\\ODText\\Style\\', get_class($style));
|
||||||
|
if (class_exists($styleClass)) {
|
||||||
|
/** @var \PhpOffice\PhpWord\Writer\ODText\Style\AbstractStyle $styleWriter Type hint */
|
||||||
|
$styleWriter = new $styleClass($xmlWriter, $style);
|
||||||
|
$styleWriter->write();
|
||||||
|
}
|
||||||
|
if ($style instanceof Paragraph) {
|
||||||
|
$paragraphStyleCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ($this->imageParagraphStyles as $style) {
|
||||||
|
$styleWriter = new \PhpOffice\PhpWord\Writer\ODText\Style\Paragraph($xmlWriter, $style);
|
||||||
|
$styleWriter->write();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -231,6 +265,7 @@ class Content extends AbstractPart
|
||||||
$elements = $container->getElements();
|
$elements = $container->getElements();
|
||||||
foreach ($elements as $element) {
|
foreach ($elements as $element) {
|
||||||
if ($element instanceof TextRun) {
|
if ($element instanceof TextRun) {
|
||||||
|
$this->getElementStyle($element, $paragraphStyleCount, $fontStyleCount);
|
||||||
$this->getContainerStyle($element, $paragraphStyleCount, $fontStyleCount);
|
$this->getContainerStyle($element, $paragraphStyleCount, $fontStyleCount);
|
||||||
} elseif ($element instanceof Text) {
|
} elseif ($element instanceof Text) {
|
||||||
$this->getElementStyle($element, $paragraphStyleCount, $fontStyleCount);
|
$this->getElementStyle($element, $paragraphStyleCount, $fontStyleCount);
|
||||||
|
|
@ -238,13 +273,19 @@ class Content extends AbstractPart
|
||||||
$style = $element->getStyle();
|
$style = $element->getStyle();
|
||||||
$style->setStyleName('fr' . $element->getMediaIndex());
|
$style->setStyleName('fr' . $element->getMediaIndex());
|
||||||
$this->autoStyles['Image'][] = $style;
|
$this->autoStyles['Image'][] = $style;
|
||||||
|
$sty = new \PhpOffice\PhpWord\Style\Paragraph();
|
||||||
|
$sty->setStyleName('IM' . $element->getMediaIndex());
|
||||||
|
$sty->setAuto();
|
||||||
|
$sty->setAlignment($style->getAlignment());
|
||||||
|
$this->imageParagraphStyles[] = $sty;
|
||||||
} elseif ($element instanceof Table) {
|
} elseif ($element instanceof Table) {
|
||||||
/** @var \PhpOffice\PhpWord\Style\Table $style */
|
/** @var \PhpOffice\PhpWord\Style\Table $style */
|
||||||
$style = $element->getStyle();
|
$style = $element->getStyle();
|
||||||
|
if (is_string($style)) {
|
||||||
|
$style = Style::getStyle($style);
|
||||||
|
}
|
||||||
if ($style === null) {
|
if ($style === null) {
|
||||||
$style = new TableStyle();
|
$style = new TableStyle();
|
||||||
} elseif (is_string($style)) {
|
|
||||||
$style = Style::getStyle($style);
|
|
||||||
}
|
}
|
||||||
$style->setStyleName($element->getElementId());
|
$style->setStyleName($element->getElementId());
|
||||||
$style->setColumnWidths($element->findFirstDefinedCellWidths());
|
$style->setColumnWidths($element->findFirstDefinedCellWidths());
|
||||||
|
|
@ -268,16 +309,34 @@ class Content extends AbstractPart
|
||||||
|
|
||||||
if ($fontStyle instanceof Font) {
|
if ($fontStyle instanceof Font) {
|
||||||
// Font
|
// Font
|
||||||
$fontStyleCount++;
|
$name = $fontStyle->getStyleName();
|
||||||
$style = $phpWord->addFontStyle("T{$fontStyleCount}", $fontStyle);
|
if (!$name) {
|
||||||
$style->setAuto();
|
$fontStyleCount++;
|
||||||
$element->setFontStyle("T{$fontStyleCount}");
|
$style = $phpWord->addFontStyle("T{$fontStyleCount}", $fontStyle, null);
|
||||||
} elseif ($paragraphStyle instanceof Paragraph) {
|
$style->setAuto();
|
||||||
|
$style->setParagraph(null);
|
||||||
|
$element->setFontStyle("T{$fontStyleCount}");
|
||||||
|
} else {
|
||||||
|
$element->setFontStyle($name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($paragraphStyle instanceof Paragraph) {
|
||||||
// Paragraph
|
// Paragraph
|
||||||
|
$name = $paragraphStyle->getStyleName();
|
||||||
|
if (!$name) {
|
||||||
|
$paragraphStyleCount++;
|
||||||
|
$style = $phpWord->addParagraphStyle("P{$paragraphStyleCount}", $paragraphStyle);
|
||||||
|
$style->setAuto();
|
||||||
|
$element->setParagraphStyle("P{$paragraphStyleCount}");
|
||||||
|
} else {
|
||||||
|
$element->setParagraphStyle($name);
|
||||||
|
}
|
||||||
|
} elseif (is_string($paragraphStyle)) {
|
||||||
$paragraphStyleCount++;
|
$paragraphStyleCount++;
|
||||||
$style = $phpWord->addParagraphStyle("P{$paragraphStyleCount}", array());
|
$parstylename = "P$paragraphStyleCount" . "_$paragraphStyle";
|
||||||
|
$style = $phpWord->addParagraphStyle($parstylename, $paragraphStyle);
|
||||||
$style->setAuto();
|
$style->setAuto();
|
||||||
$element->setParagraphStyle("P{$paragraphStyleCount}");
|
$element->setParagraphStyle($parstylename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ namespace PhpOffice\PhpWord\Writer\ODText\Part;
|
||||||
|
|
||||||
use PhpOffice\Common\XMLWriter;
|
use PhpOffice\Common\XMLWriter;
|
||||||
use PhpOffice\PhpWord\Settings;
|
use PhpOffice\PhpWord\Settings;
|
||||||
|
use PhpOffice\PhpWord\Shared\Converter;
|
||||||
use PhpOffice\PhpWord\Style;
|
use PhpOffice\PhpWord\Style;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -86,6 +87,9 @@ class Styles extends AbstractPart
|
||||||
$latinLang = $language != null && is_string($language->getLatin()) ? explode('-', $language->getLatin()) : array('fr', 'FR');
|
$latinLang = $language != null && is_string($language->getLatin()) ? explode('-', $language->getLatin()) : array('fr', 'FR');
|
||||||
$asianLang = $language != null && is_string($language->getEastAsia()) ? explode('-', $language->getEastAsia()) : array('zh', 'CN');
|
$asianLang = $language != null && is_string($language->getEastAsia()) ? explode('-', $language->getEastAsia()) : array('zh', 'CN');
|
||||||
$complexLang = $language != null && is_string($language->getBidirectional()) ? explode('-', $language->getBidirectional()) : array('hi', 'IN');
|
$complexLang = $language != null && is_string($language->getBidirectional()) ? explode('-', $language->getBidirectional()) : array('hi', 'IN');
|
||||||
|
if ($this->getParentWriter()->getPhpWord()->getSettings()->hasHideGrammaticalErrors()) {
|
||||||
|
$latinLang = $asianLang = $complexLang = array('zxx', 'none');
|
||||||
|
}
|
||||||
|
|
||||||
// Font
|
// Font
|
||||||
$xmlWriter->startElement('style:text-properties');
|
$xmlWriter->startElement('style:text-properties');
|
||||||
|
|
@ -134,24 +138,87 @@ class Styles extends AbstractPart
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write page layout styles.
|
* Convert int in twips to inches/cm then to string and append unit
|
||||||
|
*
|
||||||
|
* @param int $twips
|
||||||
|
* @param string $dflt
|
||||||
|
* @param float $factor
|
||||||
|
* return string
|
||||||
|
*/
|
||||||
|
private static function cvttwiptostr($twips, $dflt, $factor = 1.0) // Owen 2019-08-06
|
||||||
|
{
|
||||||
|
if ($twips === null) {
|
||||||
|
return $dflt;
|
||||||
|
}
|
||||||
|
$ins = (string) ($twips * $factor / Converter::INCH_TO_TWIP) . 'in';
|
||||||
|
$cms = (string) ($twips * $factor * Converter::INCH_TO_CM / Converter::INCH_TO_TWIP) . 'cm';
|
||||||
|
|
||||||
|
return (strlen($ins) < strlen($cms)) ? $ins : $cms;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* call writePageLayoutIndiv to write page layout styles for each page
|
||||||
*
|
*
|
||||||
* @param \PhpOffice\Common\XMLWriter $xmlWriter
|
* @param \PhpOffice\Common\XMLWriter $xmlWriter
|
||||||
*/
|
*/
|
||||||
private function writePageLayout(XMLWriter $xmlWriter)
|
private function writePageLayout(XMLWriter $xmlWriter) // Owen 2019-06-19
|
||||||
{
|
{
|
||||||
|
$sections = $this->getParentWriter()->getPhpWord()->getSections();
|
||||||
|
for ($i = 0; $i < count($sections); ++$i) {
|
||||||
|
$this->writePageLayoutIndiv($xmlWriter, $sections[$i], $i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write page layout styles.
|
||||||
|
*
|
||||||
|
* @param \PhpOffice\Common\XMLWriter $xmlWriter
|
||||||
|
* @param \PhpOffice\PhpWord\Element\Section $section
|
||||||
|
* @param int $sectionNbr
|
||||||
|
*/
|
||||||
|
private function writePageLayoutIndiv(XMLWriter $xmlWriter, $section, $sectionNbr)
|
||||||
|
{
|
||||||
|
$sty = $section->getStyle();
|
||||||
|
if (count($section->getHeaders()) > 0) {
|
||||||
|
$topfactor = 0.5;
|
||||||
|
} else {
|
||||||
|
$topfactor = 1.0;
|
||||||
|
}
|
||||||
|
if (count($section->getFooters()) > 0) {
|
||||||
|
$botfactor = 0.5;
|
||||||
|
} else {
|
||||||
|
$botfactor = 1.0;
|
||||||
|
}
|
||||||
|
$pwidth = '21.001cm';
|
||||||
|
$pheight = '29.7cm';
|
||||||
|
$orient = 'portrait';
|
||||||
|
$mtop = $mleft = $mright = '2.501cm';
|
||||||
|
$mbottom = '2cm';
|
||||||
|
if ($sty instanceof \PhpOffice\PhpWord\Style\Section) {
|
||||||
|
$ori = $sty->getOrientation();
|
||||||
|
if ($ori !== null) {
|
||||||
|
$orient = $ori;
|
||||||
|
}
|
||||||
|
$pwidth = self::cvttwiptostr($sty->getPageSizeW(), $pwidth);
|
||||||
|
$pheight = self::cvttwiptostr($sty->getPageSizeH(), $pheight);
|
||||||
|
$mtop = self::cvttwiptostr($sty->getMarginTop(), $mtop, $topfactor);
|
||||||
|
$mbottom = self::cvttwiptostr($sty->getMarginBottom(), $mbottom, $botfactor);
|
||||||
|
$mleft = self::cvttwiptostr($sty->getMarginRight(), $mleft);
|
||||||
|
$mright = self::cvttwiptostr($sty->getMarginLeft(), $mright);
|
||||||
|
}
|
||||||
|
|
||||||
$xmlWriter->startElement('style:page-layout');
|
$xmlWriter->startElement('style:page-layout');
|
||||||
$xmlWriter->writeAttribute('style:name', 'Mpm1');
|
$xmlWriter->writeAttribute('style:name', "Mpm$sectionNbr");
|
||||||
|
|
||||||
$xmlWriter->startElement('style:page-layout-properties');
|
$xmlWriter->startElement('style:page-layout-properties');
|
||||||
$xmlWriter->writeAttribute('fo:page-width', '21.001cm');
|
$xmlWriter->writeAttribute('fo:page-width', $pwidth);
|
||||||
$xmlWriter->writeAttribute('fo:page-height', '29.7cm');
|
$xmlWriter->writeAttribute('fo:page-height', $pheight);
|
||||||
$xmlWriter->writeAttribute('style:num-format', '1');
|
$xmlWriter->writeAttribute('style:num-format', '1');
|
||||||
$xmlWriter->writeAttribute('style:print-orientation', 'portrait');
|
$xmlWriter->writeAttribute('style:print-orientation', $orient);
|
||||||
$xmlWriter->writeAttribute('fo:margin-top', '2.501cm');
|
$xmlWriter->writeAttribute('fo:margin-top', $mtop);
|
||||||
$xmlWriter->writeAttribute('fo:margin-bottom', '2cm');
|
$xmlWriter->writeAttribute('fo:margin-bottom', $mbottom);
|
||||||
$xmlWriter->writeAttribute('fo:margin-left', '2.501cm');
|
$xmlWriter->writeAttribute('fo:margin-left', $mleft);
|
||||||
$xmlWriter->writeAttribute('fo:margin-right', '2.501cm');
|
$xmlWriter->writeAttribute('fo:margin-right', $mright);
|
||||||
$xmlWriter->writeAttribute('style:writing-mode', 'lr-tb');
|
$xmlWriter->writeAttribute('style:writing-mode', 'lr-tb');
|
||||||
$xmlWriter->writeAttribute('style:layout-grid-color', '#c0c0c0');
|
$xmlWriter->writeAttribute('style:layout-grid-color', '#c0c0c0');
|
||||||
$xmlWriter->writeAttribute('style:layout-grid-lines', '25199');
|
$xmlWriter->writeAttribute('style:layout-grid-lines', '25199');
|
||||||
|
|
@ -176,9 +243,23 @@ class Styles extends AbstractPart
|
||||||
$xmlWriter->endElement(); // style:page-layout-properties
|
$xmlWriter->endElement(); // style:page-layout-properties
|
||||||
|
|
||||||
$xmlWriter->startElement('style:header-style');
|
$xmlWriter->startElement('style:header-style');
|
||||||
|
if ($topfactor < 1.0) {
|
||||||
|
$xmlWriter->startElement('style:header-footer-properties');
|
||||||
|
$xmlWriter->writeAttribute('fo:min-height', $mtop);
|
||||||
|
$xmlWriter->writeAttribute('fo:margin-bottom', $mtop);
|
||||||
|
$xmlWriter->writeAttribute('style:dynamic-spacing', 'true');
|
||||||
|
$xmlWriter->endElement(); // style:header-footer-properties
|
||||||
|
}
|
||||||
$xmlWriter->endElement(); // style:header-style
|
$xmlWriter->endElement(); // style:header-style
|
||||||
|
|
||||||
$xmlWriter->startElement('style:footer-style');
|
$xmlWriter->startElement('style:footer-style');
|
||||||
|
if ($botfactor < 1.0) { // Owen 2019-08-03
|
||||||
|
$xmlWriter->startElement('style:header-footer-properties');
|
||||||
|
$xmlWriter->writeAttribute('fo:min-height', $mbottom);
|
||||||
|
$xmlWriter->writeAttribute('fo:margin-top', $mbottom);
|
||||||
|
$xmlWriter->writeAttribute('style:dynamic-spacing', 'true');
|
||||||
|
$xmlWriter->endElement(); // style:header-footer-properties
|
||||||
|
}
|
||||||
$xmlWriter->endElement(); // style:footer-style
|
$xmlWriter->endElement(); // style:footer-style
|
||||||
|
|
||||||
$xmlWriter->endElement(); // style:page-layout
|
$xmlWriter->endElement(); // style:page-layout
|
||||||
|
|
@ -193,11 +274,43 @@ class Styles extends AbstractPart
|
||||||
{
|
{
|
||||||
$xmlWriter->startElement('office:master-styles');
|
$xmlWriter->startElement('office:master-styles');
|
||||||
|
|
||||||
$xmlWriter->startElement('style:master-page');
|
$sections = $this->getParentWriter()->getPhpWord()->getSections();
|
||||||
$xmlWriter->writeAttribute('style:name', 'Standard');
|
for ($i = 0; $i < count($sections); ++$i) {
|
||||||
$xmlWriter->writeAttribute('style:page-layout-name', 'Mpm1');
|
$iplus1 = $i + 1;
|
||||||
$xmlWriter->endElement(); // style:master-page
|
$xmlWriter->startElement('style:master-page');
|
||||||
|
$xmlWriter->writeAttribute('style:name', "Standard$iplus1");
|
||||||
|
$xmlWriter->writeAttribute('style:page-layout-name', "Mpm$iplus1");
|
||||||
|
// Multiple headers and footers probably not supported,
|
||||||
|
// and, even if they are, I'm not sure how,
|
||||||
|
// so quit after generating one.
|
||||||
|
foreach ($sections[$i]->getHeaders() as $hdr) {
|
||||||
|
$xmlWriter->startElement('style:header');
|
||||||
|
foreach ($hdr->getElements() as $elem) {
|
||||||
|
$cl1 = get_class($elem);
|
||||||
|
$cl2 = str_replace('\\Element\\', '\\Writer\\ODText\\Element\\', $cl1);
|
||||||
|
if (class_exists($cl2)) {
|
||||||
|
$wtr = new $cl2($xmlWriter, $elem);
|
||||||
|
$wtr->write();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$xmlWriter->endElement(); // style:header
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
foreach ($sections[$i]->getFooters() as $hdr) {
|
||||||
|
$xmlWriter->startElement('style:footer');
|
||||||
|
foreach ($hdr->getElements() as $elem) {
|
||||||
|
$cl1 = get_class($elem);
|
||||||
|
$cl2 = str_replace('\\Element\\', '\\Writer\\ODText\\Element\\', $cl1);
|
||||||
|
if (class_exists($cl2)) {
|
||||||
|
$wtr = new $cl2($xmlWriter, $elem);
|
||||||
|
$wtr->write();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$xmlWriter->endElement(); // style:footer
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$xmlWriter->endElement(); // style:master-page
|
||||||
|
}
|
||||||
$xmlWriter->endElement(); // office:master-styles
|
$xmlWriter->endElement(); // office:master-styles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,14 @@ class Font extends AbstractStyle
|
||||||
}
|
}
|
||||||
$xmlWriter = $this->getXmlWriter();
|
$xmlWriter = $this->getXmlWriter();
|
||||||
|
|
||||||
|
$stylep = (method_exists($style, 'getParagraph')) ? $style->getParagraph() : null;
|
||||||
|
if ($stylep instanceof \PhpOffice\PhpWord\Style\Paragraph) {
|
||||||
|
$temp1 = clone $stylep;
|
||||||
|
$temp1->setStyleName($style->getStyleName());
|
||||||
|
$temp2 = new \PhpOffice\PhpWord\Writer\ODText\Style\Paragraph($xmlWriter, $temp1);
|
||||||
|
$temp2->write();
|
||||||
|
}
|
||||||
|
|
||||||
$xmlWriter->startElement('style:style');
|
$xmlWriter->startElement('style:style');
|
||||||
$xmlWriter->writeAttribute('style:name', $style->getStyleName());
|
$xmlWriter->writeAttribute('style:name', $style->getStyleName());
|
||||||
$xmlWriter->writeAttribute('style:family', 'text');
|
$xmlWriter->writeAttribute('style:family', 'text');
|
||||||
|
|
@ -53,7 +61,7 @@ class Font extends AbstractStyle
|
||||||
|
|
||||||
// Color
|
// Color
|
||||||
$color = $style->getColor();
|
$color = $style->getColor();
|
||||||
$xmlWriter->writeAttributeIf($color != '', 'fo:color', '#' . $color);
|
$xmlWriter->writeAttributeIf($color != '', 'fo:color', '#' . \PhpOffice\PhpWord\Shared\Converter::stringToRgb($color));
|
||||||
|
|
||||||
// Bold & italic
|
// Bold & italic
|
||||||
$xmlWriter->writeAttributeIf($style->isBold(), 'fo:font-weight', 'bold');
|
$xmlWriter->writeAttributeIf($style->isBold(), 'fo:font-weight', 'bold');
|
||||||
|
|
@ -82,6 +90,15 @@ class Font extends AbstractStyle
|
||||||
$xmlWriter->writeAttributeIf($style->isSuperScript(), 'style:text-position', 'super');
|
$xmlWriter->writeAttributeIf($style->isSuperScript(), 'style:text-position', 'super');
|
||||||
$xmlWriter->writeAttributeIf($style->isSubScript(), 'style:text-position', 'sub');
|
$xmlWriter->writeAttributeIf($style->isSubScript(), 'style:text-position', 'sub');
|
||||||
|
|
||||||
|
if ($style->isNoProof()) {
|
||||||
|
$xmlWriter->writeAttribute('fo:language', 'zxx');
|
||||||
|
$xmlWriter->writeAttribute('style:language-asian', 'zxx');
|
||||||
|
$xmlWriter->writeAttribute('style:language-complex', 'zxx');
|
||||||
|
$xmlWriter->writeAttribute('fo:country', 'none');
|
||||||
|
$xmlWriter->writeAttribute('style:country-asian', 'none');
|
||||||
|
$xmlWriter->writeAttribute('style:country-complex', 'none');
|
||||||
|
}
|
||||||
|
|
||||||
// @todo Foreground-Color
|
// @todo Foreground-Color
|
||||||
|
|
||||||
// @todo Background color
|
// @todo Background color
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
namespace PhpOffice\PhpWord\Writer\ODText\Style;
|
namespace PhpOffice\PhpWord\Writer\ODText\Style;
|
||||||
|
|
||||||
|
use PhpOffice\PhpWord\Shared\Converter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Font style writer
|
* Font style writer
|
||||||
*
|
*
|
||||||
|
|
@ -35,31 +37,120 @@ class Paragraph extends AbstractStyle
|
||||||
}
|
}
|
||||||
$xmlWriter = $this->getXmlWriter();
|
$xmlWriter = $this->getXmlWriter();
|
||||||
|
|
||||||
$marginTop = (is_null($style->getSpaceBefore()) || $style->getSpaceBefore() == 0) ? '0' : round(17.6 / $style->getSpaceBefore(), 2);
|
$marginTop = $style->getSpaceBefore();
|
||||||
$marginBottom = (is_null($style->getSpaceAfter()) || $style->getSpaceAfter() == 0) ? '0' : round(17.6 / $style->getSpaceAfter(), 2);
|
$marginBottom = $style->getSpaceAfter();
|
||||||
|
|
||||||
$xmlWriter->startElement('style:style');
|
$xmlWriter->startElement('style:style');
|
||||||
|
|
||||||
|
$styleName = $style->getStyleName();
|
||||||
|
$styleAuto = false;
|
||||||
|
$mpm = '';
|
||||||
|
$psm = '';
|
||||||
|
$pagestart = -1;
|
||||||
|
$breakafter = $breakbefore = $breakauto = false;
|
||||||
|
if ($style->isAuto()) {
|
||||||
|
if (substr($styleName, 0, 2) === 'PB') {
|
||||||
|
$styleAuto = true;
|
||||||
|
$breakafter = true;
|
||||||
|
} elseif (substr($styleName, 0, 2) === 'SB') {
|
||||||
|
$styleAuto = true;
|
||||||
|
$mpm = 'Standard' . substr($styleName, 2);
|
||||||
|
$psn = $style->getNumLevel();
|
||||||
|
if (is_numeric($psn)) {
|
||||||
|
$pagestart = (int) $psn;
|
||||||
|
}
|
||||||
|
} elseif (substr($styleName, 0, 2) === 'HD') {
|
||||||
|
$styleAuto = true;
|
||||||
|
$psm = 'Heading_' . substr($styleName, 2);
|
||||||
|
$stylep = \PhpOffice\PhpWord\Style::getStyle($psm);
|
||||||
|
if ($stylep instanceof \PhpOffice\PhpWord\Style\Font) {
|
||||||
|
if (method_exists($stylep, 'getParagraph')) {
|
||||||
|
$stylep = $stylep->getParagraph();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($stylep instanceof \PhpOffice\PhpWord\Style\Paragraph) {
|
||||||
|
if ($stylep->hasPageBreakBefore()) {
|
||||||
|
$breakbefore = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} elseif (substr($styleName, 0, 2) === 'HE') {
|
||||||
|
$styleAuto = true;
|
||||||
|
$psm = 'Heading_' . substr($styleName, 2);
|
||||||
|
$breakauto = true;
|
||||||
|
} else {
|
||||||
|
$styleAuto = true;
|
||||||
|
$psm = 'Normal';
|
||||||
|
if (preg_match('/^P\\d+_(\\w+)$/', $styleName, $matches)) {
|
||||||
|
$psm = $matches[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$xmlWriter->writeAttribute('style:name', $style->getStyleName());
|
$xmlWriter->writeAttribute('style:name', $style->getStyleName());
|
||||||
$xmlWriter->writeAttribute('style:family', 'paragraph');
|
$xmlWriter->writeAttribute('style:family', 'paragraph');
|
||||||
if ($style->isAuto()) {
|
if ($styleAuto) {
|
||||||
$xmlWriter->writeAttribute('style:parent-style-name', 'Standard');
|
$xmlWriter->writeAttributeIf($psm !== '', 'style:parent-style-name', $psm);
|
||||||
$xmlWriter->writeAttribute('style:master-page-name', 'Standard');
|
$xmlWriter->writeAttributeIf($mpm !== '', 'style:master-page-name', $mpm);
|
||||||
}
|
}
|
||||||
|
|
||||||
$xmlWriter->startElement('style:paragraph-properties');
|
$xmlWriter->startElement('style:paragraph-properties');
|
||||||
if ($style->isAuto()) {
|
if ($styleAuto) {
|
||||||
$xmlWriter->writeAttribute('style:page-number', 'auto');
|
if ($breakafter) {
|
||||||
} else {
|
$xmlWriter->writeAttribute('fo:break-after', 'page');
|
||||||
$xmlWriter->writeAttribute('fo:margin-top', $marginTop . 'cm');
|
$xmlWriter->writeAttribute('fo:margin-top', '0cm');
|
||||||
$xmlWriter->writeAttribute('fo:margin-bottom', $marginBottom . 'cm');
|
$xmlWriter->writeAttribute('fo:margin-bottom', '0cm');
|
||||||
$xmlWriter->writeAttribute('fo:text-align', $style->getAlignment());
|
} elseif ($breakbefore) {
|
||||||
|
$xmlWriter->writeAttribute('fo:break-before', 'page');
|
||||||
|
} elseif ($breakauto) {
|
||||||
|
$xmlWriter->writeAttribute('fo:break-before', 'auto');
|
||||||
|
}
|
||||||
|
if ($pagestart > 0) {
|
||||||
|
$xmlWriter->writeAttribute('style:page-number', $pagestart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!$breakafter && !$breakbefore && !$breakauto) {
|
||||||
|
$twipToPoint = Converter::INCH_TO_TWIP / Converter::INCH_TO_POINT; // 20
|
||||||
|
$xmlWriter->writeAttributeIf($marginTop !== null, 'fo:margin-top', ($marginTop / $twipToPoint) . 'pt');
|
||||||
|
$xmlWriter->writeAttributeIf($marginBottom !== null, 'fo:margin-bottom', ($marginBottom / $twipToPoint) . 'pt');
|
||||||
|
}
|
||||||
|
$temp = $style->getAlignment();
|
||||||
|
$xmlWriter->writeAttributeIf($temp !== '', 'fo:text-align', $temp);
|
||||||
|
$temp = $style->getLineHeight();
|
||||||
|
$xmlWriter->writeAttributeIf($temp !== null, 'fo:line-height', ((string) ($temp * 100) . '%'));
|
||||||
|
$xmlWriter->writeAttributeIf($style->getPageBreakBefore() === true, 'fo:break-before', 'page');
|
||||||
|
|
||||||
|
$tabs = $style->getTabs();
|
||||||
|
if ($tabs !== null && count($tabs) > 0) {
|
||||||
|
$xmlWriter->startElement('style:tab-stops');
|
||||||
|
foreach ($tabs as $tab) {
|
||||||
|
$xmlWriter->startElement('style:tab-stop');
|
||||||
|
$xmlWriter->writeAttribute('style:type', $tab->getType());
|
||||||
|
$xmlWriter->writeAttribute('style:position', (string) ($tab->getPosition() / Converter::INCH_TO_TWIP) . 'in');
|
||||||
|
$xmlWriter->endElement();
|
||||||
|
}
|
||||||
|
$xmlWriter->endElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Right to left
|
//Right to left
|
||||||
$xmlWriter->writeAttributeIf($style->isBidi(), 'style:writing-mode', 'rl-tb');
|
$xmlWriter->writeAttributeIf($style->isBidi(), 'style:writing-mode', 'rl-tb');
|
||||||
|
|
||||||
|
//Indentation
|
||||||
|
$indent = $style->getIndentation();
|
||||||
|
if ($indent instanceof \PhpOffice\PhpWord\Style\Indentation) {
|
||||||
|
$marg = $indent->getLeft();
|
||||||
|
$xmlWriter->writeAttributeIf($marg !== null, 'fo:margin-left', (string) ($marg / Converter::INCH_TO_TWIP) . 'in');
|
||||||
|
$marg = $indent->getRight();
|
||||||
|
$xmlWriter->writeAttributeIf($marg !== null, 'fo:margin-right', (string) ($marg / Converter::INCH_TO_TWIP) . 'in');
|
||||||
|
}
|
||||||
|
|
||||||
$xmlWriter->endElement(); //style:paragraph-properties
|
$xmlWriter->endElement(); //style:paragraph-properties
|
||||||
|
|
||||||
|
if ($styleAuto && substr($styleName, 0, 2) === 'SB') {
|
||||||
|
$xmlWriter->startElement('style:text-properties');
|
||||||
|
$xmlWriter->writeAttribute('text:display', 'none');
|
||||||
|
$xmlWriter->endElement();
|
||||||
|
}
|
||||||
|
|
||||||
$xmlWriter->endElement(); //style:style
|
$xmlWriter->endElement(); //style:style
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
<?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
|
||||||
|
* @copyright 2010-2018 PHPWord contributors
|
||||||
|
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpWord\Writer\ODText\Style;
|
||||||
|
|
||||||
|
use PhpOffice\PhpWord\Style\Image;
|
||||||
|
use PhpOffice\PhpWord\TestHelperDOCX;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test class for PhpOffice\PhpWord\Writer\Word2007\Style\Font
|
||||||
|
*
|
||||||
|
* @coversDefaultClass \PhpOffice\PhpWord\Writer\Word2007\Style\Frame
|
||||||
|
* @runTestsInSeparateProcesses
|
||||||
|
*/
|
||||||
|
class ImageTest extends \PHPUnit\Framework\TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Executed after each method of the class
|
||||||
|
*/
|
||||||
|
public function tearDown()
|
||||||
|
{
|
||||||
|
TestHelperDOCX::clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test writing image
|
||||||
|
*/
|
||||||
|
public function testImage1()
|
||||||
|
{
|
||||||
|
$phpWord = new \PhpOffice\PhpWord\PhpWord();
|
||||||
|
$section = $phpWord->addSection();
|
||||||
|
$section->addImage(__DIR__ . '/../../../_files/images/earth.jpg');
|
||||||
|
$section->addImage(__DIR__ . '/../../../_files/images/mario.gif', array('align' => 'end'));
|
||||||
|
$doc = TestHelperDOCX::getDocument($phpWord, 'ODText');
|
||||||
|
$s2a = '/office:document-content/office:automatic-styles';
|
||||||
|
$element = "$s2a/style:style[3]";
|
||||||
|
$this->assertEquals('IM1', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$element .= '/style:paragraph-properties';
|
||||||
|
$this->assertEquals('', $doc->getElementAttribute($element, 'fo:text-align'));
|
||||||
|
$element = "$s2a/style:style[4]";
|
||||||
|
$this->assertEquals('IM2', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$element .= '/style:paragraph-properties';
|
||||||
|
$this->assertEquals('end', $doc->getElementAttribute($element, 'fo:text-align'));
|
||||||
|
|
||||||
|
$path = '/office:document-content/office:body/office:text/text:section/text:p[2]';
|
||||||
|
$this->assertTrue($doc->elementExists($path));
|
||||||
|
$this->assertEquals('IM1', $doc->getElementAttribute($path, 'text:style-name'));
|
||||||
|
$path = '/office:document-content/office:body/office:text/text:section/text:p[3]';
|
||||||
|
$this->assertTrue($doc->elementExists($path));
|
||||||
|
$this->assertEquals('IM2', $doc->getElementAttribute($path, 'text:style-name'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -26,6 +26,14 @@ use PhpOffice\PhpWord\TestHelperDOCX;
|
||||||
*/
|
*/
|
||||||
class ElementTest extends \PHPUnit\Framework\TestCase
|
class ElementTest extends \PHPUnit\Framework\TestCase
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Executed after each method of the class
|
||||||
|
*/
|
||||||
|
public function tearDown()
|
||||||
|
{
|
||||||
|
TestHelperDOCX::clear();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test unmatched elements
|
* Test unmatched elements
|
||||||
*/
|
*/
|
||||||
|
|
@ -39,10 +47,168 @@ class ElementTest extends \PHPUnit\Framework\TestCase
|
||||||
$object = new $objectClass($xmlWriter, $newElement);
|
$object = new $objectClass($xmlWriter, $newElement);
|
||||||
$object->write();
|
$object->write();
|
||||||
|
|
||||||
$this->assertEquals('', $xmlWriter->getData());
|
self::assertEquals('', $xmlWriter->getData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ODT Line Element not yet implemented
|
||||||
|
// ODT Bookmark not yet implemented
|
||||||
|
// ODT Table with style name not yet implemented (Word test defective)
|
||||||
|
// ODT Shape Elements not yet implemented
|
||||||
|
// ODT Chart Elements not yet implemented
|
||||||
|
// ODT adding Field to Section not yet implemented
|
||||||
|
// ODT List not yet implemented
|
||||||
|
// ODT Macro Button not yet implemented
|
||||||
|
// ODT Form Field not yet implemented
|
||||||
|
// ODT SDT not yet implemented
|
||||||
|
// ODT Comment not yet implemented
|
||||||
|
// ODT Track Changes implemented, possibly not correctly
|
||||||
|
// ODT List Item not yet implemented
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test link element
|
||||||
|
*/
|
||||||
|
public function testLinkElement()
|
||||||
|
{
|
||||||
|
$phpWord = new PhpWord();
|
||||||
|
$section = $phpWord->addSection();
|
||||||
|
|
||||||
|
$extlink = 'https://github.com/PHPOffice/PHPWord';
|
||||||
|
$section->addLink($extlink);
|
||||||
|
$intlink = 'internal_link';
|
||||||
|
$section->addLink($intlink, null, null, null, true);
|
||||||
|
$doc = TestHelperDOCX::getDocument($phpWord, 'ODText');
|
||||||
|
|
||||||
|
$p2t = '/office:document-content/office:body/office:text/text:section';
|
||||||
|
$element = "$p2t/text:p[2]/text:a";
|
||||||
|
self::assertTrue($doc->elementExists($element));
|
||||||
|
self::assertEquals($extlink, $doc->getElementAttribute($element, 'xlink:href'));
|
||||||
|
|
||||||
|
$element = "$p2t/text:p[3]/text:a";
|
||||||
|
self::assertTrue($doc->elementExists($element));
|
||||||
|
self::assertEquals("#$intlink", $doc->getElementAttribute($element, 'xlink:href'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic test for table element
|
||||||
|
*/
|
||||||
|
public function testTableElements()
|
||||||
|
{
|
||||||
|
$phpWord = new PhpWord();
|
||||||
|
$section = $phpWord->addSection();
|
||||||
|
|
||||||
|
$table = $section->addTable(array('alignment' => \PhpOffice\PhpWord\SimpleType\JcTable::CENTER));
|
||||||
|
$table->addRow(900);
|
||||||
|
$table->addCell(2000)->addText('Row 1');
|
||||||
|
$table->addCell(2000)->addText('Row 2');
|
||||||
|
$table->addCell(2000)->addText('Row 3');
|
||||||
|
$table->addCell(2000)->addText('Row 4');
|
||||||
|
|
||||||
|
$doc = TestHelperDOCX::getDocument($phpWord, 'ODText');
|
||||||
|
|
||||||
|
$p2s = '/office:document-content/office:automatic-styles';
|
||||||
|
$tableStyleNum = 1;
|
||||||
|
$tableStyleName = '';
|
||||||
|
while ($tableStyleName === '') {
|
||||||
|
$element = "$p2s/style:style[$tableStyleNum]";
|
||||||
|
if (!$doc->elementExists($element)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ($doc->getElementAttribute($element, 'style:family') === 'table') {
|
||||||
|
$tableStyleName = $doc->getElementAttribute($element, 'style:name');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++$tableStyleNum;
|
||||||
|
}
|
||||||
|
self::AssertNotEquals('', $tableStyleName);
|
||||||
|
$element = "$element/style:table-properties";
|
||||||
|
self::assertTrue($doc->elementExists($element));
|
||||||
|
self::assertEquals(\PhpOffice\PhpWord\SimpleType\JcTable::CENTER, $doc->getElementAttribute($element, 'table:align'));
|
||||||
|
$p2t = '/office:document-content/office:body/office:text/text:section';
|
||||||
|
$tableRootElement = "$p2t/table:table";
|
||||||
|
self::assertTrue($doc->elementExists($tableRootElement));
|
||||||
|
self::assertEquals($tableStyleName, $doc->getElementAttribute($tableRootElement, 'table:style'));
|
||||||
|
self::assertTrue($doc->elementExists($tableRootElement . '/table:table-column[4]'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test Title and Headings
|
||||||
|
*/
|
||||||
|
public function testTitleAndHeading()
|
||||||
|
{
|
||||||
|
$phpWord = new PhpWord();
|
||||||
|
$phpWord->addTitleStyle(0, array('size' => 14, 'italic' => true));
|
||||||
|
$phpWord->addTitleStyle(1, array('size' => 20, 'color' => '333333', 'bold' => true));
|
||||||
|
|
||||||
|
$section = $phpWord->addSection();
|
||||||
|
$section->addTitle('This is a title', 0);
|
||||||
|
$section->addTitle('Heading 1', 1);
|
||||||
|
|
||||||
|
$doc = TestHelperDOCX::getDocument($phpWord, 'ODText');
|
||||||
|
|
||||||
|
$p2t = '/office:document-content/office:body/office:text/text:section';
|
||||||
|
$element = "$p2t/text:h[1]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('HE0', $doc->getElementAttribute($element, 'text:style-name'));
|
||||||
|
$this->assertEquals('0', $doc->getElementAttribute($element, 'text:outline-level'));
|
||||||
|
$span = "$element/text:span";
|
||||||
|
$this->assertTrue($doc->elementExists($span));
|
||||||
|
$this->assertEquals('This is a title', $doc->getElement($span)->textContent);
|
||||||
|
$this->assertEquals('Title', $doc->getElementAttribute($span, 'text:style-name'));
|
||||||
|
|
||||||
|
$element = "$p2t/text:h[2]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('HD1', $doc->getElementAttribute($element, 'text:style-name'));
|
||||||
|
$this->assertEquals('1', $doc->getElementAttribute($element, 'text:outline-level'));
|
||||||
|
$span = "$element/text:span";
|
||||||
|
$this->assertTrue($doc->elementExists($span));
|
||||||
|
$this->assertEquals('Heading 1', $doc->getElement($span)->textContent);
|
||||||
|
$this->assertEquals('Heading_1', $doc->getElementAttribute($span, 'text:style-name'));
|
||||||
|
|
||||||
|
$doc->setDefaultFile('styles.xml');
|
||||||
|
$element = '/office:document-styles/office:styles/style:style[1]';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('Title', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$element .= '/style:text-properties';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('14pt', $doc->getElementAttribute($element, 'fo:font-size'));
|
||||||
|
$this->assertEquals('italic', $doc->getElementAttribute($element, 'fo:font-style'));
|
||||||
|
$this->assertEquals('', $doc->getElementAttribute($element, 'fo:font-weight'));
|
||||||
|
$this->assertEquals('', $doc->getElementAttribute($element, 'fo:color'));
|
||||||
|
|
||||||
|
$element = '/office:document-styles/office:styles/style:style[2]';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('Heading_1', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$element .= '/style:text-properties';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('20pt', $doc->getElementAttribute($element, 'fo:font-size'));
|
||||||
|
$this->assertEquals('', $doc->getElementAttribute($element, 'fo:font-style'));
|
||||||
|
$this->assertEquals('bold', $doc->getElementAttribute($element, 'fo:font-weight'));
|
||||||
|
$this->assertEquals('#333333', $doc->getElementAttribute($element, 'fo:color'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test correct writing of text with ampersand in it
|
||||||
|
*/
|
||||||
|
public function testTextWithAmpersand()
|
||||||
|
{
|
||||||
|
$esc = \PhpOffice\PhpWord\Settings::isOutputEscapingEnabled();
|
||||||
|
\PhpOffice\PhpWord\Settings::setOutputEscapingEnabled(true);
|
||||||
|
$phpWord = new PhpWord();
|
||||||
|
$section = $phpWord->addSection();
|
||||||
|
$txt = 'this text contains an & (ampersand)';
|
||||||
|
$section->addText($txt);
|
||||||
|
|
||||||
|
$doc = TestHelperDOCX::getDocument($phpWord, 'ODText');
|
||||||
|
\PhpOffice\PhpWord\Settings::setOutputEscapingEnabled($esc);
|
||||||
|
$p2t = '/office:document-content/office:body/office:text/text:section';
|
||||||
|
$element = "$p2t/text:p[2]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$span = "$element/text:span";
|
||||||
|
$this->assertTrue($doc->elementExists($span));
|
||||||
|
$this->assertEquals($txt, $doc->getElement($span)->nodeValue);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test PageBreak
|
* Test PageBreak
|
||||||
*/
|
*/
|
||||||
|
|
@ -55,8 +221,8 @@ class ElementTest extends \PHPUnit\Framework\TestCase
|
||||||
|
|
||||||
$doc = TestHelperDOCX::getDocument($phpWord, 'ODText');
|
$doc = TestHelperDOCX::getDocument($phpWord, 'ODText');
|
||||||
|
|
||||||
$element = '/office:document-content/office:body/office:text/text:section/text:p[2]';
|
$element = '/office:document-content/office:body/office:text/text:section/text:p[3]';
|
||||||
$this->assertTrue($doc->elementExists($element, 'content.xml'));
|
self::assertTrue($doc->elementExists($element, 'content.xml'));
|
||||||
$this->assertEquals('P1', $doc->getElementAttribute($element, 'text:style-name', 'content.xml'));
|
self::assertEquals('PB', $doc->getElementAttribute($element, 'text:style-name', 'content.xml'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ class ContentTest extends \PHPUnit\Framework\TestCase
|
||||||
|
|
||||||
$doc = TestHelperDOCX::getDocument($phpWord, 'ODText');
|
$doc = TestHelperDOCX::getDocument($phpWord, 'ODText');
|
||||||
|
|
||||||
$element = '/office:document-content/office:body/office:text/text:section/text:p';
|
$element = '/office:document-content/office:body/office:text/text:section/text:p[2]';
|
||||||
$this->assertEquals($expected, $doc->getElement($element, 'content.xml')->nodeValue);
|
$this->assertEquals($expected, $doc->getElement($element, 'content.xml')->nodeValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,131 @@
|
||||||
|
<?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
|
||||||
|
* @copyright 2010-2018 PHPWord contributors
|
||||||
|
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpWord\Writer\ODText\Style;
|
||||||
|
|
||||||
|
use PhpOffice\PhpWord\TestHelperDOCX;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test class for Headers, Footers, Tabs in ODT
|
||||||
|
*/
|
||||||
|
class FontTest extends \PHPUnit\Framework\TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Executed after each method of the class
|
||||||
|
*/
|
||||||
|
public function tearDown()
|
||||||
|
{
|
||||||
|
TestHelperDOCX::clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test colors
|
||||||
|
*/
|
||||||
|
public function testColors()
|
||||||
|
{
|
||||||
|
$phpWord = new \PhpOffice\PhpWord\PhpWord();
|
||||||
|
$section = $phpWord->addSection();
|
||||||
|
$section->addText('This is red (800) in rtf/html, default in docx/odt', array('color' => '800'));
|
||||||
|
$section->addText('This should be cyanish (008787)', array('color' => '008787'));
|
||||||
|
$section->addText('This should be dark green (FGCOLOR_DARKGREEN)', array('color' => \PhpOffice\PhpWord\Style\Font::FGCOLOR_DARKGREEN));
|
||||||
|
$section->addText('This color is default (unknow)', array('color' => 'unknow'));
|
||||||
|
|
||||||
|
$doc = TestHelperDOCX::getDocument($phpWord, 'ODText');
|
||||||
|
$s2a = '/office:document-content/office:automatic-styles';
|
||||||
|
$this->assertTrue($doc->elementExists($s2a));
|
||||||
|
$s2t = '/office:document-content/office:body/office:text/text:section';
|
||||||
|
$this->assertTrue($doc->elementExists($s2t));
|
||||||
|
|
||||||
|
$element = "$s2a/style:style[5]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$style = $doc->getElementAttribute($element, 'style:name');
|
||||||
|
$element .= '/style:text-properties';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('#008787', $doc->getElementAttribute($element, 'fo:color'));
|
||||||
|
$span = "$s2t/text:p[3]/text:span";
|
||||||
|
$this->assertTrue($doc->elementExists($span));
|
||||||
|
$this->assertEquals($style, $doc->getElementAttribute($span, 'text:style-name'));
|
||||||
|
$this->assertEquals('This should be cyanish (008787)', $doc->getElement($span)->nodeValue);
|
||||||
|
|
||||||
|
$element = "$s2a/style:style[7]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$style = $doc->getElementAttribute($element, 'style:name');
|
||||||
|
$element .= '/style:text-properties';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('#006400', $doc->getElementAttribute($element, 'fo:color'));
|
||||||
|
$span = "$s2t/text:p[4]/text:span";
|
||||||
|
$this->assertTrue($doc->elementExists($span));
|
||||||
|
$this->assertEquals($style, $doc->getElementAttribute($span, 'text:style-name'));
|
||||||
|
$this->assertEquals('This should be dark green (FGCOLOR_DARKGREEN)', $doc->getElement($span)->nodeValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test noproof
|
||||||
|
*/
|
||||||
|
public function testNoProof()
|
||||||
|
{
|
||||||
|
$phpWord = new \PhpOffice\PhpWord\PhpWord();
|
||||||
|
$section = $phpWord->addSection();
|
||||||
|
$section->addText('Noproof not specified', array('color' => 'black'));
|
||||||
|
$section->addText('Noproof is true', array('color' => 'black', 'noproof' => true));
|
||||||
|
$section->addText('Noproof is false', array('color' => 'black', 'noproof' => false));
|
||||||
|
|
||||||
|
$doc = TestHelperDOCX::getDocument($phpWord, 'ODText');
|
||||||
|
$s2a = '/office:document-content/office:automatic-styles';
|
||||||
|
$this->assertTrue($doc->elementExists($s2a));
|
||||||
|
$s2t = '/office:document-content/office:body/office:text/text:section';
|
||||||
|
$this->assertTrue($doc->elementExists($s2t));
|
||||||
|
|
||||||
|
$element = "$s2a/style:style[3]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$style = $doc->getElementAttribute($element, 'style:name');
|
||||||
|
$element .= '/style:text-properties';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('', $doc->getElementAttribute($element, 'fo:language'));
|
||||||
|
$span = "$s2t/text:p[2]/text:span";
|
||||||
|
$this->assertTrue($doc->elementExists($span));
|
||||||
|
$this->assertEquals($style, $doc->getElementAttribute($span, 'text:style-name'));
|
||||||
|
$this->assertEquals('Noproof not specified', $doc->getElement($span)->nodeValue);
|
||||||
|
|
||||||
|
$element = "$s2a/style:style[5]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$style = $doc->getElementAttribute($element, 'style:name');
|
||||||
|
$element .= '/style:text-properties';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('zxx', $doc->getElementAttribute($element, 'fo:language'));
|
||||||
|
$this->assertEquals('zxx', $doc->getElementAttribute($element, 'style:language-asian'));
|
||||||
|
$this->assertEquals('zxx', $doc->getElementAttribute($element, 'style:language-complex'));
|
||||||
|
$this->assertEquals('none', $doc->getElementAttribute($element, 'fo:country'));
|
||||||
|
$this->assertEquals('none', $doc->getElementAttribute($element, 'style:country-asian'));
|
||||||
|
$this->assertEquals('none', $doc->getElementAttribute($element, 'style:country-complex'));
|
||||||
|
$span = "$s2t/text:p[3]/text:span";
|
||||||
|
$this->assertTrue($doc->elementExists($span));
|
||||||
|
$this->assertEquals($style, $doc->getElementAttribute($span, 'text:style-name'));
|
||||||
|
$this->assertEquals('Noproof is true', $doc->getElement($span)->nodeValue);
|
||||||
|
|
||||||
|
$element = "$s2a/style:style[7]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$style = $doc->getElementAttribute($element, 'style:name');
|
||||||
|
$element .= '/style:text-properties';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('', $doc->getElementAttribute($element, 'fo:language'));
|
||||||
|
$span = "$s2t/text:p[4]/text:span";
|
||||||
|
$this->assertTrue($doc->elementExists($span));
|
||||||
|
$this->assertEquals($style, $doc->getElementAttribute($span, 'text:style-name'));
|
||||||
|
$this->assertEquals('Noproof is false', $doc->getElement($span)->nodeValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,434 @@
|
||||||
|
<?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
|
||||||
|
* @copyright 2010-2018 PHPWord contributors
|
||||||
|
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpWord\Writer\ODText\Style;
|
||||||
|
|
||||||
|
use PhpOffice\PhpWord\PhpWord;
|
||||||
|
use PhpOffice\PhpWord\Shared\Converter;
|
||||||
|
use PhpOffice\PhpWord\TestHelperDOCX;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test class for Headers, Footers, Tabs in ODT
|
||||||
|
*/
|
||||||
|
class ParagraphTest extends \PHPUnit\Framework\TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Executed after each method of the class
|
||||||
|
*/
|
||||||
|
public function tearDown()
|
||||||
|
{
|
||||||
|
TestHelperDOCX::clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test page break
|
||||||
|
*/
|
||||||
|
public function testPageBreak()
|
||||||
|
{
|
||||||
|
$phpWord = new PhpWord();
|
||||||
|
$section = $phpWord->addSection();
|
||||||
|
$section->addText('Text on first page');
|
||||||
|
$section->addPageBreak();
|
||||||
|
$section->addText('Text on second page');
|
||||||
|
|
||||||
|
$doc = TestHelperDOCX::getDocument($phpWord, 'ODText');
|
||||||
|
|
||||||
|
$s2a = '/office:document-content/office:automatic-styles';
|
||||||
|
$element = "$s2a/style:style[1]";
|
||||||
|
$this->assertEquals('PB', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$element .= '/style:paragraph-properties';
|
||||||
|
$this->assertEquals('page', $doc->getElementAttribute($element, 'fo:break-after'));
|
||||||
|
$this->assertEquals('0cm', $doc->getElementAttribute($element, 'fo:margin-top'));
|
||||||
|
$this->assertEquals('0cm', $doc->getElementAttribute($element, 'fo:margin-bottom'));
|
||||||
|
|
||||||
|
$s2a = '/office:document-content/office:body/office:text/text:section';
|
||||||
|
$element = "$s2a/text:p[3]";
|
||||||
|
$this->assertEquals('PB', $doc->getElementAttribute($element, 'text:style-name'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test normal/indent
|
||||||
|
*/
|
||||||
|
public function testNormalIndent()
|
||||||
|
{
|
||||||
|
$phpWord = new PhpWord();
|
||||||
|
$cvt = Converter::INCH_TO_TWIP;
|
||||||
|
$indent1 = array('indentation' => array('left' => 0.50 * $cvt));
|
||||||
|
$indent2 = array('indentation' => array('left' => 1.00 * $cvt, 'right' => 1.05 * $cvt));
|
||||||
|
$indent3 = array('indentation' => array('left' => -0.50 * $cvt));
|
||||||
|
$indent4 = array('indentation' => array('left' => 0 * $cvt));
|
||||||
|
$phpWord->setDefaultParagraphStyle($indent1);
|
||||||
|
$section = $phpWord->addSection();
|
||||||
|
$section->addText('Should use default indent (0.5)');
|
||||||
|
$section->addText('Should use non-default indent (1.0) on both sides, and here\'s an extra long line to prove it', null, $indent2);
|
||||||
|
$section->addText('Should use non-default indent (-0.5)', null, $indent3);
|
||||||
|
$section->addText('Should use non-default indent (0)', null, $indent4);
|
||||||
|
|
||||||
|
$doc = TestHelperDOCX::getDocument($phpWord, 'ODText');
|
||||||
|
$s2a = '/office:document-content/office:automatic-styles';
|
||||||
|
$this->assertTrue($doc->elementExists($s2a));
|
||||||
|
|
||||||
|
$element = "$s2a/style:style[4]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('Normal', $doc->getElementAttribute($element, 'style:parent-style-name'));
|
||||||
|
$element .= '/style:paragraph-properties';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('', $doc->getElementAttribute($element, 'fo:margin-left'));
|
||||||
|
$this->assertEquals('', $doc->getElementAttribute($element, 'fo:margin-right'));
|
||||||
|
|
||||||
|
$element = "$s2a/style:style[6]/style:paragraph-properties";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('1in', $doc->getElementAttribute($element, 'fo:margin-left'));
|
||||||
|
$this->assertEquals('1.05in', $doc->getElementAttribute($element, 'fo:margin-right'));
|
||||||
|
|
||||||
|
$element = "$s2a/style:style[8]/style:paragraph-properties";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('-0.5in', $doc->getElementAttribute($element, 'fo:margin-left'));
|
||||||
|
$this->assertEquals('0in', $doc->getElementAttribute($element, 'fo:margin-right'));
|
||||||
|
|
||||||
|
$element = "$s2a/style:style[10]/style:paragraph-properties";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('0in', $doc->getElementAttribute($element, 'fo:margin-left'));
|
||||||
|
$this->assertEquals('0in', $doc->getElementAttribute($element, 'fo:margin-right'));
|
||||||
|
|
||||||
|
$doc->setDefaultFile('styles.xml');
|
||||||
|
$element = '/office:document-styles/office:styles/style:style';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('Normal', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$element .= '/style:paragraph-properties';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('0.5in', $doc->getElementAttribute($element, 'fo:margin-left'));
|
||||||
|
$this->assertEquals('0in', $doc->getElementAttribute($element, 'fo:margin-right'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test textAlign
|
||||||
|
*/
|
||||||
|
public function testTextAlign()
|
||||||
|
{
|
||||||
|
$phpWord = new PhpWord();
|
||||||
|
$align1 = array('alignment' => 'end');
|
||||||
|
$align2 = array('alignment' => 'start');
|
||||||
|
$phpWord->setDefaultParagraphStyle($align1);
|
||||||
|
$section = $phpWord->addSection();
|
||||||
|
$section->addText('Should use default alignment (right for this doc)');
|
||||||
|
$section->addText('Explicit left alignment', null, $align2);
|
||||||
|
$section->addText('Explicit right alignment', null, $align1);
|
||||||
|
|
||||||
|
$doc = TestHelperDOCX::getDocument($phpWord, 'ODText');
|
||||||
|
$s2a = '/office:document-content/office:automatic-styles';
|
||||||
|
$this->assertTrue($doc->elementExists($s2a));
|
||||||
|
|
||||||
|
$element = "$s2a/style:style[4]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('Normal', $doc->getElementAttribute($element, 'style:parent-style-name'));
|
||||||
|
$element .= '/style:paragraph-properties';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('', $doc->getElementAttribute($element, 'fo:text-align'));
|
||||||
|
|
||||||
|
$element = "$s2a/style:style[6]/style:paragraph-properties";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('start', $doc->getElementAttribute($element, 'fo:text-align'));
|
||||||
|
|
||||||
|
$element = "$s2a/style:style[8]/style:paragraph-properties";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('end', $doc->getElementAttribute($element, 'fo:text-align'));
|
||||||
|
|
||||||
|
$doc->setDefaultFile('styles.xml');
|
||||||
|
$element = '/office:document-styles/office:styles/style:style';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('Normal', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$element .= '/style:paragraph-properties';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('end', $doc->getElementAttribute($element, 'fo:text-align'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test lineHeight
|
||||||
|
*/
|
||||||
|
public function testLineHeight()
|
||||||
|
{
|
||||||
|
$phpWord = new PhpWord();
|
||||||
|
$section = $phpWord->addSection();
|
||||||
|
$section->addText('Should use line height 1.08, and here\'s a long line which ought to overflow onto a second line to prove it', null, array('lineHeight' => 1.08));
|
||||||
|
$section->addText('Should use line height 1.20, and here\'s a long line which ought to overflow onto a second line to prove it', null, array('lineHeight' => 1.20));
|
||||||
|
$section->addText('Should use line height 0.90, and here\'s a long line which ought to overflow onto a second line to prove it', null, array('lineHeight' => 0.90));
|
||||||
|
|
||||||
|
$doc = TestHelperDOCX::getDocument($phpWord, 'ODText');
|
||||||
|
$s2a = '/office:document-content/office:automatic-styles';
|
||||||
|
$this->assertTrue($doc->elementExists($s2a));
|
||||||
|
|
||||||
|
$element = "$s2a/style:style[4]/style:paragraph-properties";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('108%', $doc->getElementAttribute($element, 'fo:line-height'));
|
||||||
|
|
||||||
|
$element = "$s2a/style:style[6]/style:paragraph-properties";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('120%', $doc->getElementAttribute($element, 'fo:line-height'));
|
||||||
|
|
||||||
|
$element = "$s2a/style:style[8]/style:paragraph-properties";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('90%', $doc->getElementAttribute($element, 'fo:line-height'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test SpaceBeforeAfter
|
||||||
|
*/
|
||||||
|
public function testSpaceBeforeAfter()
|
||||||
|
{
|
||||||
|
$phpWord = new PhpWord();
|
||||||
|
$phpWord->setDefaultParagraphStyle(array('spaceBefore' => 0, 'spaceAfter' => 0));
|
||||||
|
$section = $phpWord->addSection();
|
||||||
|
$section->addText('No spacing between this paragraph and next');
|
||||||
|
$section->addText('No spacing between this paragraph and previous');
|
||||||
|
$section->addText('No spacing before this but 100 after', null, array('spaceAfter' => 100));
|
||||||
|
$section->addText('No spacing for this paragraph but previous specified 100 after and next specifies 100 before');
|
||||||
|
$section->addText('No spacing after this but 100 before', null, array('spaceBefore' => 100));
|
||||||
|
$section->addText('No spacing before this paragraph');
|
||||||
|
|
||||||
|
$doc = TestHelperDOCX::getDocument($phpWord, 'ODText');
|
||||||
|
$s2a = '/office:document-content/office:automatic-styles';
|
||||||
|
$this->assertTrue($doc->elementExists($s2a));
|
||||||
|
|
||||||
|
$element = "$s2a/style:style[8]/style:paragraph-properties";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('', $doc->getElementAttribute($element, 'fo:margin-top'));
|
||||||
|
$this->assertEquals('5pt', $doc->getElementAttribute($element, 'fo:margin-bottom'));
|
||||||
|
|
||||||
|
$element = "$s2a/style:style[12]/style:paragraph-properties";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('5pt', $doc->getElementAttribute($element, 'fo:margin-top'));
|
||||||
|
$this->assertEquals('', $doc->getElementAttribute($element, 'fo:margin-bottom'));
|
||||||
|
|
||||||
|
$doc->setDefaultFile('styles.xml');
|
||||||
|
$element = '/office:document-styles/office:styles/style:style';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('Normal', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$element .= '/style:paragraph-properties';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('0pt', $doc->getElementAttribute($element, 'fo:margin-top'));
|
||||||
|
$this->assertEquals('0pt', $doc->getElementAttribute($element, 'fo:margin-bottom'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test Page Break Before
|
||||||
|
*/
|
||||||
|
public function testPageBreakBefore()
|
||||||
|
{
|
||||||
|
$phpWord = new PhpWord();
|
||||||
|
$section = $phpWord->addSection();
|
||||||
|
$section->addText('This is my first paragraph.');
|
||||||
|
$section->addText('This is my second paragraph, on a new page.', null, array('pageBreakBefore' => true));
|
||||||
|
$section->addText('This is my third paragraph, on same page as second.');
|
||||||
|
$section->addText('This is my fourth paragraph, on a new page.', null, array('pageBreakBefore' => true));
|
||||||
|
|
||||||
|
$doc = TestHelperDOCX::getDocument($phpWord, 'ODText');
|
||||||
|
$s2a = '/office:document-content/office:automatic-styles';
|
||||||
|
$this->assertTrue($doc->elementExists($s2a));
|
||||||
|
|
||||||
|
$element = "$s2a/style:style[4]/style:paragraph-properties";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('', $doc->getElementAttribute($element, 'fo:break-before'));
|
||||||
|
$element = "$s2a/style:style[6]/style:paragraph-properties";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('page', $doc->getElementAttribute($element, 'fo:break-before'));
|
||||||
|
$element = "$s2a/style:style[8]/style:paragraph-properties";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('', $doc->getElementAttribute($element, 'fo:break-before'));
|
||||||
|
$element = "$s2a/style:style[10]/style:paragraph-properties";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('page', $doc->getElementAttribute($element, 'fo:break-before'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test Heading Page Break Before
|
||||||
|
*/
|
||||||
|
public function testHeadingPageBreakBefore()
|
||||||
|
{
|
||||||
|
$phpWord = new PhpWord();
|
||||||
|
$phpWord->addTitleStyle(1, null, array('pageBreakBefore' => true));
|
||||||
|
$phpWord->addTitleStyle(2, null, array());
|
||||||
|
$section = $phpWord->addSection();
|
||||||
|
$section->addTitle('Section1 Heading1 #1', 1);
|
||||||
|
$section->addTitle('Section1 Heading2 #1', 2);
|
||||||
|
$section->addTitle('Section1 Heading1 #2', 1);
|
||||||
|
$section->addTitle('Section1 Heading2 #2', 2);
|
||||||
|
$section = $phpWord->addSection();
|
||||||
|
$section->addTitle('Section2 Heading1 #1', 1);
|
||||||
|
$section->addTitle('Section2 Heading2 #1', 2);
|
||||||
|
|
||||||
|
$doc = TestHelperDOCX::getDocument($phpWord, 'ODText');
|
||||||
|
$s2a = '/office:document-content/office:automatic-styles';
|
||||||
|
$this->assertTrue($doc->elementExists($s2a));
|
||||||
|
|
||||||
|
$element = "$s2a/style:style[4]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('HD1', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$this->assertEquals('Heading_1', $doc->getElementAttribute($element, 'style:parent-style-name'));
|
||||||
|
$element .= '/style:paragraph-properties';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('page', $doc->getElementAttribute($element, 'fo:break-before'));
|
||||||
|
|
||||||
|
$element = "$s2a/style:style[5]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('HE1', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$this->assertEquals('Heading_1', $doc->getElementAttribute($element, 'style:parent-style-name'));
|
||||||
|
$element .= '/style:paragraph-properties';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('auto', $doc->getElementAttribute($element, 'fo:break-before'));
|
||||||
|
|
||||||
|
$element = "$s2a/style:style[6]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('HD2', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$this->assertEquals('Heading_2', $doc->getElementAttribute($element, 'style:parent-style-name'));
|
||||||
|
$element .= '/style:paragraph-properties';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('', $doc->getElementAttribute($element, 'fo:break-before'));
|
||||||
|
|
||||||
|
$element = "$s2a/style:style[7]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('HE2', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$this->assertEquals('Heading_2', $doc->getElementAttribute($element, 'style:parent-style-name'));
|
||||||
|
$element .= '/style:paragraph-properties';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('auto', $doc->getElementAttribute($element, 'fo:break-before'));
|
||||||
|
|
||||||
|
$s2a = '/office:document-content/office:body/office:text/text:section[1]';
|
||||||
|
$this->assertTrue($doc->elementExists($s2a));
|
||||||
|
$element = "$s2a/text:h[1]";
|
||||||
|
$this->assertEquals('HE1', $doc->getElementAttribute($element, 'text:style-name'));
|
||||||
|
$this->assertEquals('1', $doc->getElementAttribute($element, 'text:outline-level'));
|
||||||
|
$element .= '/text:span';
|
||||||
|
$this->assertEquals('Heading_1', $doc->getElementAttribute($element, 'text:style-name'));
|
||||||
|
$element = "$s2a/text:h[2]";
|
||||||
|
$this->assertEquals('HD2', $doc->getElementAttribute($element, 'text:style-name'));
|
||||||
|
$this->assertEquals('2', $doc->getElementAttribute($element, 'text:outline-level'));
|
||||||
|
$element .= '/text:span';
|
||||||
|
$this->assertEquals('Heading_2', $doc->getElementAttribute($element, 'text:style-name'));
|
||||||
|
$element = "$s2a/text:h[3]";
|
||||||
|
$this->assertEquals('HD1', $doc->getElementAttribute($element, 'text:style-name'));
|
||||||
|
$this->assertEquals('1', $doc->getElementAttribute($element, 'text:outline-level'));
|
||||||
|
$element .= '/text:span';
|
||||||
|
$this->assertEquals('Heading_1', $doc->getElementAttribute($element, 'text:style-name'));
|
||||||
|
$element = "$s2a/text:h[4]";
|
||||||
|
$this->assertEquals('HD2', $doc->getElementAttribute($element, 'text:style-name'));
|
||||||
|
$this->assertEquals('2', $doc->getElementAttribute($element, 'text:outline-level'));
|
||||||
|
$element .= '/text:span';
|
||||||
|
$this->assertEquals('Heading_2', $doc->getElementAttribute($element, 'text:style-name'));
|
||||||
|
|
||||||
|
$s2a = '/office:document-content/office:body/office:text/text:section[2]';
|
||||||
|
$this->assertTrue($doc->elementExists($s2a));
|
||||||
|
$element = "$s2a/text:h[1]";
|
||||||
|
$this->assertEquals('HE1', $doc->getElementAttribute($element, 'text:style-name'));
|
||||||
|
$this->assertEquals('1', $doc->getElementAttribute($element, 'text:outline-level'));
|
||||||
|
$element .= '/text:span';
|
||||||
|
$this->assertEquals('Heading_1', $doc->getElementAttribute($element, 'text:style-name'));
|
||||||
|
$element = "$s2a/text:h[2]";
|
||||||
|
$this->assertEquals('HD2', $doc->getElementAttribute($element, 'text:style-name'));
|
||||||
|
$this->assertEquals('2', $doc->getElementAttribute($element, 'text:outline-level'));
|
||||||
|
$element .= '/text:span';
|
||||||
|
$this->assertEquals('Heading_2', $doc->getElementAttribute($element, 'text:style-name'));
|
||||||
|
|
||||||
|
$doc->setDefaultFile('styles.xml');
|
||||||
|
$s2a = '/office:document-styles/office:styles';
|
||||||
|
$this->assertTrue($doc->elementExists($s2a));
|
||||||
|
$element = "$s2a/style:style[1]";
|
||||||
|
$this->assertEquals('Heading_1', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$this->assertEquals('paragraph', $doc->getElementAttribute($element, 'style:family'));
|
||||||
|
$element .= '/style:paragraph-properties';
|
||||||
|
$this->assertEquals('page', $doc->getElementAttribute($element, 'fo:break-before'));
|
||||||
|
$element = "$s2a/style:style[3]";
|
||||||
|
$this->assertEquals('Heading_2', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$this->assertEquals('paragraph', $doc->getElementAttribute($element, 'style:family'));
|
||||||
|
$element .= '/style:paragraph-properties';
|
||||||
|
$this->assertEquals('', $doc->getElementAttribute($element, 'fo:break-before'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test text run paragraph style using named style
|
||||||
|
*/
|
||||||
|
public function testTextRun()
|
||||||
|
{
|
||||||
|
$phpWord = new \PhpOffice\PhpWord\PhpWord();
|
||||||
|
$phpWord->addParagraphStyle('parstyle1', array('align' => 'start'));
|
||||||
|
$phpWord->addParagraphStyle('parstyle2', array('align' => 'end'));
|
||||||
|
$section = $phpWord->addSection();
|
||||||
|
$trx = $section->addTextRun('parstyle1');
|
||||||
|
$trx->addText('First text in textrun. ');
|
||||||
|
$trx->addText('Second text - paragraph style is specified but ignored.', null, 'parstyle2');
|
||||||
|
$section->addText('Third text added to section not textrun - paragraph style is specified and used.', null, 'parstyle2');
|
||||||
|
|
||||||
|
$doc = TestHelperDOCX::getDocument($phpWord, 'ODText');
|
||||||
|
$s2a = '/office:document-content/office:automatic-styles';
|
||||||
|
$element = "$s2a/style:style[3]";
|
||||||
|
$this->assertEquals('P1_parstyle1', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$this->assertEquals('parstyle1', $doc->getElementAttribute($element, 'style:parent-style-name'));
|
||||||
|
$element = "$s2a/style:style[9]";
|
||||||
|
$this->assertEquals('P4_parstyle2', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$this->assertEquals('parstyle2', $doc->getElementAttribute($element, 'style:parent-style-name'));
|
||||||
|
|
||||||
|
$s2a = '/office:document-content/office:body/office:text/text:section';
|
||||||
|
$element = "$s2a/text:p[2]";
|
||||||
|
$this->assertEquals('P1_parstyle1', $doc->getElementAttribute($element, 'text:style-name'));
|
||||||
|
$element = "$s2a/text:p[3]";
|
||||||
|
$this->assertEquals('P4_parstyle2', $doc->getElementAttribute($element, 'text:style-name'));
|
||||||
|
|
||||||
|
$doc->setDefaultFile('styles.xml');
|
||||||
|
$element = '/office:document-styles/office:styles/style:style[1]';
|
||||||
|
$this->assertEquals('parstyle1', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$element .= '/style:paragraph-properties';
|
||||||
|
$this->assertEquals('start', $doc->getElementAttribute($element, 'fo:text-align'));
|
||||||
|
$element = '/office:document-styles/office:styles/style:style[2]';
|
||||||
|
$this->assertEquals('parstyle2', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$element .= '/style:paragraph-properties';
|
||||||
|
$this->assertEquals('end', $doc->getElementAttribute($element, 'fo:text-align'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test text run paragraph style using unnamed style
|
||||||
|
*/
|
||||||
|
public function testTextRunUnnamed()
|
||||||
|
{
|
||||||
|
$phpWord = new \PhpOffice\PhpWord\PhpWord();
|
||||||
|
$parstyle1 = array('align' => 'start');
|
||||||
|
$parstyle2 = array('align' => 'end');
|
||||||
|
$section = $phpWord->addSection();
|
||||||
|
$trx = $section->addTextRun($parstyle1);
|
||||||
|
$trx->addText('First text in textrun. ');
|
||||||
|
$trx->addText('Second text - paragraph style is specified but ignored.', null, $parstyle2);
|
||||||
|
$section->addText('Third text added to section not textrun - paragraph style is specified and used.', null, $parstyle2);
|
||||||
|
|
||||||
|
$doc = TestHelperDOCX::getDocument($phpWord, 'ODText');
|
||||||
|
$s2a = '/office:document-content/office:automatic-styles';
|
||||||
|
$element = "$s2a/style:style[3]";
|
||||||
|
$this->assertEquals('P1', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$this->assertEquals('Normal', $doc->getElementAttribute($element, 'style:parent-style-name'));
|
||||||
|
$element .= '/style:paragraph-properties';
|
||||||
|
$this->assertEquals('start', $doc->getElementAttribute($element, 'fo:text-align'));
|
||||||
|
$element = "$s2a/style:style[9]";
|
||||||
|
$this->assertEquals('P4', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$this->assertEquals('Normal', $doc->getElementAttribute($element, 'style:parent-style-name'));
|
||||||
|
$element .= '/style:paragraph-properties';
|
||||||
|
$this->assertEquals('end', $doc->getElementAttribute($element, 'fo:text-align'));
|
||||||
|
|
||||||
|
$s2a = '/office:document-content/office:body/office:text/text:section';
|
||||||
|
$element = "$s2a/text:p[2]";
|
||||||
|
$this->assertEquals('P1', $doc->getElementAttribute($element, 'text:style-name'));
|
||||||
|
$element = "$s2a/text:p[3]";
|
||||||
|
$this->assertEquals('P4', $doc->getElementAttribute($element, 'text:style-name'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,249 @@
|
||||||
|
<?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
|
||||||
|
* @copyright 2010-2018 PHPWord contributors
|
||||||
|
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace PhpOffice\PhpWord\Writer\ODText\Style;
|
||||||
|
|
||||||
|
use PhpOffice\PhpWord\PhpWord;
|
||||||
|
use PhpOffice\PhpWord\TestHelperDOCX;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test class for Headers, Footers, Tabs in ODT
|
||||||
|
*/
|
||||||
|
class SectionTest extends \PHPUnit\Framework\TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Executed after each method of the class
|
||||||
|
*/
|
||||||
|
public function tearDown()
|
||||||
|
{
|
||||||
|
TestHelperDOCX::clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test various section styles, including header, footer, and tabs
|
||||||
|
*/
|
||||||
|
public function testHeaderFooterTabs()
|
||||||
|
{
|
||||||
|
$phpWord = new \PhpOffice\PhpWord\PhpWord();
|
||||||
|
$margins = \PhpOffice\PhpWord\Shared\Converter::INCH_TO_TWIP;
|
||||||
|
$phpWord->addFontStyle('hdrstyle1', array('name' => 'Courier New', 'size' => 8));
|
||||||
|
$section = $phpWord->addSection(array('paperSize' => 'Letter', 'marginTop' => $margins, 'marginBottom' => $margins));
|
||||||
|
$header = $section->createHeader();
|
||||||
|
$phpWord->addParagraphStyle('centerheader', array('align' => 'center'));
|
||||||
|
$header->addText('Centered Header', 'hdrstyle1', 'centerheader');
|
||||||
|
$footer = $section->createFooter();
|
||||||
|
$sizew = $section->getStyle()->getPageSizeW();
|
||||||
|
$sizel = $section->getStyle()->getMarginLeft();
|
||||||
|
$sizer = $section->getStyle()->getMarginRight();
|
||||||
|
$footerwidth = $sizew - $sizel - $sizer;
|
||||||
|
$phpWord->addParagraphStyle(
|
||||||
|
'footerTab',
|
||||||
|
array(
|
||||||
|
'tabs' => array(
|
||||||
|
new \PhpOffice\PhpWord\Style\Tab('center', (int) ($footerwidth / 2)),
|
||||||
|
new \PhpOffice\PhpWord\Style\Tab('right', (int) $footerwidth),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$textrun = $footer->addTextRun('footerTab');
|
||||||
|
$textrun->addText('Left footer', 'hdrstyle1');
|
||||||
|
$textrun->addText("\t", 'hdrstyle1');
|
||||||
|
$fld = $textrun->addField('DATE');
|
||||||
|
$fld->setFontStyle('hdrstyle1');
|
||||||
|
$textrun->addText("\t", 'hdrstyle1');
|
||||||
|
$textrun->addText('Page ', 'hdrstyle1');
|
||||||
|
$fld = $textrun->addField('PAGE');
|
||||||
|
$fld->setFontStyle('hdrstyle1');
|
||||||
|
$textrun->addText(' of ', 'hdrstyle1');
|
||||||
|
$fld = $textrun->addField('NUMPAGES');
|
||||||
|
$fld->setFontStyle('hdrstyle1');
|
||||||
|
$section->addText('First page');
|
||||||
|
$section->addPageBreak();
|
||||||
|
$section->addText('Second page');
|
||||||
|
$section->addPageBreak();
|
||||||
|
$section->addText('Third page');
|
||||||
|
|
||||||
|
$doc = TestHelperDOCX::getDocument($phpWord, 'ODText');
|
||||||
|
$doc->setDefaultFile('styles.xml');
|
||||||
|
$s2a = '/office:document-styles/office:automatic-styles';
|
||||||
|
$element = "$s2a/style:page-layout/style:page-layout-properties";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('8.5in', $doc->getElementAttribute($element, 'fo:page-width'));
|
||||||
|
$this->assertEquals('11in', $doc->getElementAttribute($element, 'fo:page-height'));
|
||||||
|
$this->assertEquals('0.5in', $doc->getElementAttribute($element, 'fo:margin-top'));
|
||||||
|
$this->assertEquals('0.5in', $doc->getElementAttribute($element, 'fo:margin-bottom'));
|
||||||
|
|
||||||
|
$s2s = '/office:document-styles/office:styles';
|
||||||
|
$element = "$s2s/style:style[1]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('hdrstyle1', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$tprop = "$element/style:text-properties";
|
||||||
|
$this->assertTrue($doc->elementExists($tprop));
|
||||||
|
$this->assertEquals('Courier New', $doc->getElementAttribute($tprop, 'style:font-name'));
|
||||||
|
|
||||||
|
$element = "$s2s/style:style[2]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('centerheader', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$tprop = "$element/style:paragraph-properties";
|
||||||
|
$this->assertTrue($doc->elementExists($tprop));
|
||||||
|
$this->assertEquals('center', $doc->getElementAttribute($tprop, 'fo:text-align'));
|
||||||
|
|
||||||
|
$element = "$s2s/style:style[3]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('footerTab', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$tprop = "$element/style:paragraph-properties/style:tab-stops";
|
||||||
|
$this->assertTrue($doc->elementExists($tprop));
|
||||||
|
$tstop = "$tprop/style:tab-stop[1]";
|
||||||
|
$this->assertTrue($doc->elementExists($tstop));
|
||||||
|
$this->assertEquals('center', $doc->getElementAttribute($tstop, 'style:type'));
|
||||||
|
$this->assertEquals('3.25in', $doc->getElementAttribute($tstop, 'style:position'));
|
||||||
|
$tstop = "$tprop/style:tab-stop[2]";
|
||||||
|
$this->assertTrue($doc->elementExists($tstop));
|
||||||
|
$this->assertEquals('right', $doc->getElementAttribute($tstop, 'style:type'));
|
||||||
|
$this->assertEquals('6.5in', $doc->getElementAttribute($tstop, 'style:position'));
|
||||||
|
|
||||||
|
$s2s = '/office:document-styles/office:master-styles/style:master-page/style:footer/text:p';
|
||||||
|
$this->assertTrue($doc->elementExists($s2s));
|
||||||
|
$element = "$s2s/text:span[1]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('hdrstyle1', $doc->getElementAttribute($element, 'text:style-name'));
|
||||||
|
$this->assertEquals('Left footer', $doc->getElement($element)->nodeValue);
|
||||||
|
$element = "$s2s/text:span[2]/text:tab";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$element = "$s2s/text:span[3]/text:date";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$element = "$s2s/text:span[4]/text:tab";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$element = "$s2s/text:span[5]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('Page', $doc->getElement($element)->nodeValue);
|
||||||
|
$this->assertTrue($doc->elementExists("$element/text:s"));
|
||||||
|
$element = "$s2s/text:span[6]/text:page-number";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$element = "$s2s/text:span[7]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('of', $doc->getElement($element)->nodeValue);
|
||||||
|
$this->assertTrue($doc->elementExists("$element/text:s"));
|
||||||
|
$this->assertTrue($doc->elementExists("$element/text:s[2]"));
|
||||||
|
$element = "$s2s/text:span[8]/text:page-count";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test HideErrors
|
||||||
|
*/
|
||||||
|
public function testHideErrors()
|
||||||
|
{
|
||||||
|
$phpWord = new PhpWord();
|
||||||
|
$phpWord->getSettings()->setHideGrammaticalErrors(true);
|
||||||
|
$phpWord->getSettings()->setHideSpellingErrors(true);
|
||||||
|
$phpWord->getSettings()->setThemeFontLang(new \PhpOffice\PhpWord\Style\Language('en-US'));
|
||||||
|
$phpWord->getSettings()->getThemeFontLang()->setLangId(\PhpOffice\PhpWord\Style\Language::EN_US_ID);
|
||||||
|
$section = $phpWord->addSection();
|
||||||
|
$section->addText('Here is a paragraph with some speling errorz');
|
||||||
|
|
||||||
|
$doc = TestHelperDOCX::getDocument($phpWord, 'ODText');
|
||||||
|
$doc->setDefaultFile('styles.xml');
|
||||||
|
$element = '/office:document-styles/office:styles/style:default-style/style:text-properties';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('zxx', $doc->getElementAttribute($element, 'fo:language'));
|
||||||
|
$this->assertEquals('zxx', $doc->getElementAttribute($element, 'style:language-asian'));
|
||||||
|
$this->assertEquals('zxx', $doc->getElementAttribute($element, 'style:language-complex'));
|
||||||
|
$this->assertEquals('none', $doc->getElementAttribute($element, 'fo:country'));
|
||||||
|
$this->assertEquals('none', $doc->getElementAttribute($element, 'style:country-asian'));
|
||||||
|
$this->assertEquals('none', $doc->getElementAttribute($element, 'style:country-complex'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test SpaceBeforeAfter
|
||||||
|
*/
|
||||||
|
public function testMultipleSections()
|
||||||
|
{
|
||||||
|
$phpWord = new PhpWord();
|
||||||
|
$section = $phpWord->addSection(array('paperSize' => 'Letter', 'Orientation' => 'portrait'));
|
||||||
|
$section->addText('This section uses Letter paper in portrait orientation.');
|
||||||
|
$section = $phpWord->addSection(array('paperSize' => 'A4', 'Orientation' => 'landscape', 'pageNumberingStart' => '9'));
|
||||||
|
$header = $section->createHeader();
|
||||||
|
$header->addField('PAGE');
|
||||||
|
$section->addText('This section uses A4 paper in landscape orientation. It should have a page break beforehand. It artificially starts on page 9.');
|
||||||
|
|
||||||
|
$doc = TestHelperDOCX::getDocument($phpWord, 'ODText');
|
||||||
|
$s2a = '/office:document-content/office:automatic-styles';
|
||||||
|
$s2t = '/office:document-content/office:body/office:text';
|
||||||
|
$this->assertTrue($doc->elementExists($s2a));
|
||||||
|
$this->assertTrue($doc->elementExists($s2t));
|
||||||
|
|
||||||
|
$element = "$s2a/style:style[2]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('SB1', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$this->assertEquals('Standard1', $doc->getElementAttribute($element, 'style:master-page-name'));
|
||||||
|
$element .= '/style:text-properties';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('none', $doc->getElementAttribute($element, 'text:display'));
|
||||||
|
$element = "$s2a/style:style[3]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('SB2', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$this->assertEquals('Standard2', $doc->getElementAttribute($element, 'style:master-page-name'));
|
||||||
|
$elemen2 = "$element/style:paragraph-properties";
|
||||||
|
$this->assertEquals('9', $doc->getElementAttribute($elemen2, 'style:page-number'));
|
||||||
|
$element .= '/style:text-properties';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('none', $doc->getElementAttribute($element, 'text:display'));
|
||||||
|
|
||||||
|
$element = "$s2t/text:section[1]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$element .= '/text:p[1]';
|
||||||
|
$this->assertEquals('SB1', $doc->getElementAttribute($element, 'text:style-name'));
|
||||||
|
$element = "$s2t/text:section[2]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$element .= '/text:p[1]';
|
||||||
|
$this->assertEquals('SB2', $doc->getElementAttribute($element, 'text:style-name'));
|
||||||
|
|
||||||
|
$doc->setDefaultFile('styles.xml');
|
||||||
|
$s2a = '/office:document-styles/office:automatic-styles';
|
||||||
|
$this->assertTrue($doc->elementExists($s2a));
|
||||||
|
|
||||||
|
$element = "$s2a/style:page-layout[1]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('Mpm1', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$element .= '/style:page-layout-properties';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('8.5in', $doc->getElementAttribute($element, 'fo:page-width'));
|
||||||
|
$this->assertEquals('11in', $doc->getElementAttribute($element, 'fo:page-height'));
|
||||||
|
$this->assertEquals('portrait', $doc->getElementAttribute($element, 'style:print-orientation'));
|
||||||
|
|
||||||
|
$element = "$s2a/style:page-layout[2]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('Mpm2', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$element .= '/style:page-layout-properties';
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('29.7cm', $doc->getElementAttribute($element, 'fo:page-width'));
|
||||||
|
$this->assertEquals('21cm', $doc->getElementAttribute($element, 'fo:page-height'));
|
||||||
|
$this->assertEquals('landscape', $doc->getElementAttribute($element, 'style:print-orientation'));
|
||||||
|
|
||||||
|
$s2a = '/office:document-styles/office:master-styles';
|
||||||
|
$this->assertTrue($doc->elementExists($s2a));
|
||||||
|
$element = "$s2a/style:master-page[1]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('Standard1', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$this->assertEquals('Mpm1', $doc->getElementAttribute($element, 'style:page-layout-name'));
|
||||||
|
$element = "$s2a/style:master-page[2]";
|
||||||
|
$this->assertTrue($doc->elementExists($element));
|
||||||
|
$this->assertEquals('Standard2', $doc->getElementAttribute($element, 'style:name'));
|
||||||
|
$this->assertEquals('Mpm2', $doc->getElementAttribute($element, 'style:page-layout-name'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -63,7 +63,12 @@ class TestHelperDOCX
|
||||||
$zip->close();
|
$zip->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new XmlDocument(Settings::getTempDir() . '/PhpWord_Unit_Test/');
|
$doc = new XmlDocument(Settings::getTempDir() . '/PhpWord_Unit_Test/');
|
||||||
|
if ($writerName === 'ODText') {
|
||||||
|
$doc->setDefaultFile('content.xml');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $doc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,37 @@ class XmlDocument
|
||||||
*/
|
*/
|
||||||
private $file;
|
private $file;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default file name
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $defaultFile = 'word/document.xml';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get default file
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDefaultFile()
|
||||||
|
{
|
||||||
|
return $this->defaultFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set default file
|
||||||
|
*
|
||||||
|
* @param string $file
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function setDefaultFile($file)
|
||||||
|
{
|
||||||
|
$temp = $this->defaultFile;
|
||||||
|
$this->defaultFile = $file;
|
||||||
|
|
||||||
|
return $temp;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create new instance
|
* Create new instance
|
||||||
*
|
*
|
||||||
|
|
@ -66,8 +97,11 @@ class XmlDocument
|
||||||
* @param string $file
|
* @param string $file
|
||||||
* @return \DOMDocument
|
* @return \DOMDocument
|
||||||
*/
|
*/
|
||||||
public function getFileDom($file = 'word/document.xml')
|
public function getFileDom($file = '')
|
||||||
{
|
{
|
||||||
|
if (!$file) {
|
||||||
|
$file = $this->defaultFile;
|
||||||
|
}
|
||||||
if (null !== $this->dom && $file === $this->file) {
|
if (null !== $this->dom && $file === $this->file) {
|
||||||
return $this->dom;
|
return $this->dom;
|
||||||
}
|
}
|
||||||
|
|
@ -91,8 +125,11 @@ class XmlDocument
|
||||||
* @param string $file
|
* @param string $file
|
||||||
* @return \DOMNodeList
|
* @return \DOMNodeList
|
||||||
*/
|
*/
|
||||||
public function getNodeList($path, $file = 'word/document.xml')
|
public function getNodeList($path, $file = '')
|
||||||
{
|
{
|
||||||
|
if (!$file) {
|
||||||
|
$file = $this->defaultFile;
|
||||||
|
}
|
||||||
if (null === $this->dom || $file !== $this->file) {
|
if (null === $this->dom || $file !== $this->file) {
|
||||||
$this->getFileDom($file);
|
$this->getFileDom($file);
|
||||||
}
|
}
|
||||||
|
|
@ -112,8 +149,11 @@ class XmlDocument
|
||||||
* @param string $file
|
* @param string $file
|
||||||
* @return \DOMElement
|
* @return \DOMElement
|
||||||
*/
|
*/
|
||||||
public function getElement($path, $file = 'word/document.xml')
|
public function getElement($path, $file = '')
|
||||||
{
|
{
|
||||||
|
if (!$file) {
|
||||||
|
$file = $this->defaultFile;
|
||||||
|
}
|
||||||
$elements = $this->getNodeList($path, $file);
|
$elements = $this->getNodeList($path, $file);
|
||||||
|
|
||||||
return $elements->item(0);
|
return $elements->item(0);
|
||||||
|
|
@ -147,8 +187,12 @@ class XmlDocument
|
||||||
* @param string $file
|
* @param string $file
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getElementAttribute($path, $attribute, $file = 'word/document.xml')
|
public function getElementAttribute($path, $attribute, $file = '')
|
||||||
{
|
{
|
||||||
|
if (!$file) {
|
||||||
|
$file = $this->defaultFile;
|
||||||
|
}
|
||||||
|
|
||||||
return $this->getElement($path, $file)->getAttribute($attribute);
|
return $this->getElement($path, $file)->getAttribute($attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -159,8 +203,11 @@ class XmlDocument
|
||||||
* @param string $file
|
* @param string $file
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function elementExists($path, $file = 'word/document.xml')
|
public function elementExists($path, $file = '')
|
||||||
{
|
{
|
||||||
|
if (!$file) {
|
||||||
|
$file = $this->defaultFile;
|
||||||
|
}
|
||||||
$nodeList = $this->getNodeList($path, $file);
|
$nodeList = $this->getNodeList($path, $file);
|
||||||
|
|
||||||
return $nodeList->length != 0;
|
return $nodeList->length != 0;
|
||||||
|
|
@ -173,8 +220,11 @@ class XmlDocument
|
||||||
* @param string $file
|
* @param string $file
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function printXml($path = '/', $file = 'word/document.xml')
|
public function printXml($path = '/', $file = '')
|
||||||
{
|
{
|
||||||
|
if (!$file) {
|
||||||
|
$file = $this->defaultFile;
|
||||||
|
}
|
||||||
$element = $this->getElement($path, $file);
|
$element = $this->getElement($path, $file);
|
||||||
if ($element instanceof \DOMDocument) {
|
if ($element instanceof \DOMDocument) {
|
||||||
$element->formatOutput = true;
|
$element->formatOutput = true;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue