fix reading of docx default style (#1238)

This commit is contained in:
troosan 2018-01-12 23:42:22 +01:00 committed by GitHub
parent 4a530d1d97
commit 99b04f0353
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 115 additions and 26 deletions

View File

@ -9,6 +9,9 @@ v0.15.0 (?? ??? 2018)
- Parsing of "align" HTML attribute - @troosan #1231
### Fixed
- fix reading of docx default style - @troosan #1238
v0.14.0 (29 Dec 2017)
----------------------
@ -58,6 +61,8 @@ This version brings compatibility with PHP 7.0 & 7.1
### Deprecated
- PhpWord->getProtection(), get it from the settings instead PhpWord->getSettings()->getDocumentProtection();
v0.13.0 (31 July 2016)
-------------------
This release brings several improvements in `TemplateProcessor`, automatic output escaping feature for OOXML, ODF, HTML, and RTF (turned off, by default).
@ -77,7 +82,7 @@ Manual installation feature has been dropped since the release. Please, use [Com
- Improved error message for the case when `autoload.php` is not found. - @RomanSyroeshko #371
- Renamed the `align` option of `NumberingLevel`, `Frame`, `Table`, and `Paragraph` styles into `alignment`. - @RomanSyroeshko
- Improved performance of `TemplateProcessor::setValue()`. - @kazitanvirahsan #614, #617
- Fixed some HTML tags not rendering any output (p, header & table) - #257, #324 - @twmobius and @garethellis
- Fixed some HTML tags not rendering any output (p, header & table) - #257, #324 - @twmobius and @garethellis
### Deprecated
- `getAlign` and `setAlign` methods of `NumberingLevel`, `Frame`, `Table`, and `Paragraph` styles.

View File

@ -160,7 +160,7 @@ Parameters:
- ``$text``. Text that appears in the document.
- ``$depth``. Depth of list item.
- ``$fontStyle``. See :ref:`font-style`.
- ``$listStyle``. List style of the current element TYPE\_NUMBER,
- ``$listStyle``. List style of the current element TYPE\_NUMBER,
TYPE\_ALPHANUM, TYPE\_BULLET\_FILLED, etc. See list of constants in PHPWord\\Style\\ListItem.
- ``$paragraphStyle``. See :ref:`paragraph-style`.
@ -345,7 +345,7 @@ The footnote numbering can be controlled by setting the FootnoteProperties on th
.. code-block:: php
$fp = new PhpWord\SimpleType\FootnoteProperties();
//sets the position of the footnote (pageBottom (default), beneathText, sectEnd, docEnd)
//sets the position of the footnote (pageBottom (default), beneathText, sectEnd, docEnd)
$fp->setPos(FootnoteProperties::POSITION_DOC_END);
//set the number format to use (decimal (default), upperRoman, upperLetter, ...)
$fp->setNumFmt(FootnoteProperties::NUMBER_FORMAT_LOWER_ROMAN);
@ -353,7 +353,6 @@ The footnote numbering can be controlled by setting the FootnoteProperties on th
$fp->setNumStart(2);
//when to restart counting (continuous (default), eachSect, eachPage)
$fp->setNumRestart(FootnoteProperties::RESTART_NUMBER_EACH_PAGE);
//And finaly, set it on the Section
$section->setFootnoteProperties($properties);
@ -379,7 +378,7 @@ To be completed
Fields
------
Currently the following fields are supported:
Currently the following fields are supported:
- PAGE
- NUMPAGES

View File

@ -167,7 +167,6 @@ Use mirror margins to set up facing pages for double-sided documents, such as bo
$phpWord->getSettings()->setMirrorMargins(true);
Spelling and grammatical checks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -191,7 +190,7 @@ You can also specify the status of the spell and grammar checks, marking spellin
Track Revisions
~~~~~~~~~~~~~~~
Track changes can be activated using ``setTrackRevisions``, you can furture specify
Track changes can be activated using ``setTrackRevisions``, you can furture specify
- Not to use move syntax, instead moved items will be seen as deleted in one place and added in another
- Not track formatting revisions

View File

@ -51,7 +51,6 @@ Example:
}
}
Using samples
-------------

View File

@ -307,7 +307,7 @@ abstract class AbstractPart
$styleNode = $xmlReader->getElement('w:pPr', $domNode);
$styleDefs = array(
'styleName' => array(self::READ_VALUE, 'w:pStyle'),
'styleName' => array(self::READ_VALUE, array('w:pStyle', 'w:name')),
'alignment' => array(self::READ_VALUE, 'w:jc'),
'basedOn' => array(self::READ_VALUE, 'w:basedOn'),
'next' => array(self::READ_VALUE, 'w:next'),
@ -349,9 +349,9 @@ abstract class AbstractPart
$styleNode = $xmlReader->getElement('w:rPr', $domNode);
$styleDefs = array(
'styleName' => array(self::READ_VALUE, 'w:rStyle'),
'name' => array(self::READ_VALUE, 'w:rFonts', 'w:ascii'),
'name' => array(self::READ_VALUE, 'w:rFonts', array('w:ascii', 'w:hAnsi', 'w:eastAsia', 'w:cs')),
'hint' => array(self::READ_VALUE, 'w:rFonts', 'w:hint'),
'size' => array(self::READ_SIZE, 'w:sz'),
'size' => array(self::READ_SIZE, array('w:sz', 'w:szCs')),
'color' => array(self::READ_VALUE, 'w:color'),
'underline' => array(self::READ_VALUE, 'w:u'),
'bold' => array(self::READ_TRUE, 'w:b'),
@ -364,9 +364,7 @@ abstract class AbstractPart
'subScript' => array(self::READ_EQUAL, 'w:vertAlign', 'w:val', 'subscript'),
'fgColor' => array(self::READ_VALUE, 'w:highlight'),
'rtl' => array(self::READ_TRUE, 'w:rtl'),
'font-latin' => array(self::READ_VALUE, 'w:font', 'w:val'),
'font-eastAsia' => array(self::READ_VALUE, 'w:font', 'w:eastAsia'),
'font-bidi' => array(self::READ_VALUE, 'w:font', 'w:bidi'),
'lang' => array(self::READ_VALUE, 'w:lang'),
);
return $this->readStyleDefs($xmlReader, $styleNode, $styleDefs);
@ -400,6 +398,7 @@ abstract class AbstractPart
$ucfSide = ucfirst($side);
$styleDefs["border{$ucfSide}Size"] = array(self::READ_VALUE, "w:tblBorders/w:$side", 'w:sz');
$styleDefs["border{$ucfSide}Color"] = array(self::READ_VALUE, "w:tblBorders/w:$side", 'w:color');
$styleDefs["border{$ucfSide}Style"] = array(self::READ_VALUE, "w:tblBorders/w:$side", 'w:val');
}
$style = $this->readStyleDefs($xmlReader, $styleNode, $styleDefs);
}
@ -428,6 +427,54 @@ abstract class AbstractPart
return $this->readStyleDefs($xmlReader, $domNode, $styleDefs);
}
/**
* Returns the first child element found
*
* @param XMLReader $xmlReader
* @param \DOMElement $parentNode
* @param string|array $elements
* @return string|null
*/
private function findPossibleElement(XMLReader $xmlReader, \DOMElement $parentNode = null, $elements)
{
if (is_array($elements)) {
//if element is an array, we take the first element that exists in the XML
foreach ($elements as $possibleElement) {
if ($xmlReader->elementExists($possibleElement, $parentNode)) {
return $possibleElement;
}
}
} else {
return $elements;
}
return null;
}
/**
* Returns the first attribute found
*
* @param XMLReader $xmlReader
* @param \DOMElement $node
* @param string|array $attributes
* @return string|null
*/
private function findPossibleAttribute(XMLReader $xmlReader, \DOMElement $node, $attributes)
{
//if attribute is an array, we take the first attribute that exists in the XML
if (is_array($attributes)) {
foreach ($attributes as $possibleAttribute) {
if ($xmlReader->getAttribute($possibleAttribute, $node)) {
return $possibleAttribute;
}
}
} else {
return $attributes;
}
return null;
}
/**
* Read style definition
*
@ -442,11 +489,18 @@ abstract class AbstractPart
$styles = array();
foreach ($styleDefs as $styleProp => $styleVal) {
@list($method, $element, $attribute, $expected) = $styleVal;
list($method, $element, $attribute, $expected) = array_pad($styleVal, 4, null);
$element = $this->findPossibleElement($xmlReader, $parentNode, $element);
if ($element === null) {
continue;
}
if ($xmlReader->elementExists($element, $parentNode)) {
$node = $xmlReader->getElement($element, $parentNode);
$attribute = $this->findPossibleAttribute($xmlReader, $node, $attribute);
// Use w:val as default if no attribute assigned
$attribute = ($attribute === null) ? 'w:val' : $attribute;
$attributeValue = $xmlReader->getAttribute($attribute, $node);

View File

@ -80,8 +80,8 @@ class Settings extends AbstractPart
$themeFontLang = new Language();
$themeFontLang->setLatin($val);
$themeFontLang->setLatin($eastAsia);
$themeFontLang->setLatin($bidi);
$themeFontLang->setEastAsia($eastAsia);
$themeFontLang->setBidirectional($bidi);
$phpWord->getSettings()->setThemeFontLang($themeFontLang);
}

View File

@ -19,6 +19,7 @@ namespace PhpOffice\PhpWord\Reader\Word2007;
use PhpOffice\Common\XMLReader;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\Style\Language;
/**
* Styles reader
@ -37,6 +38,28 @@ class Styles extends AbstractPart
$xmlReader = new XMLReader();
$xmlReader->getDomFromZip($this->docFile, $this->xmlFile);
$fontDefaults = $xmlReader->getElement('w:docDefaults/w:rPrDefault');
if ($fontDefaults !== null) {
$fontDefaultStyle = $this->readFontStyle($xmlReader, $fontDefaults);
if (array_key_exists('name', $fontDefaultStyle)) {
$phpWord->setDefaultFontName($fontDefaultStyle['name']);
}
if (array_key_exists('size', $fontDefaultStyle)) {
$phpWord->setDefaultFontSize($fontDefaultStyle['size']);
}
if (array_key_exists('lang', $fontDefaultStyle)) {
$phpWord->getSettings()->setThemeFontLang(new Language($fontDefaultStyle['lang']));
}
}
$paragraphDefaults = $xmlReader->getElement('w:docDefaults/w:pPrDefault');
if ($paragraphDefaults !== null) {
$paragraphDefaultStyle = $this->readParagraphStyle($xmlReader, $paragraphDefaults);
if ($paragraphDefaultStyle != null) {
$phpWord->setDefaultParagraphStyle();
}
}
$nodes = $xmlReader->getElements('w:style');
if ($nodes->length > 0) {
foreach ($nodes as $node) {

View File

@ -20,7 +20,6 @@ namespace PhpOffice\PhpWord\Style;
use PhpOffice\Common\Text;
use PhpOffice\PhpWord\Exception\InvalidStyleException;
use PhpOffice\PhpWord\SimpleType\Jc;
use PhpOffice\PhpWord\SimpleType\LineSpacingRule;
use PhpOffice\PhpWord\SimpleType\TextAlignment;
/**

View File

@ -154,12 +154,12 @@ class Shape extends AbstractElement
case 'arc':
case 'line':
$points = explode(' ', $value);
@list($start, $end) = $points;
list($start, $end) = array_pad($points, 2, null);
$points = array('start' => $start, 'end' => $end);
break;
case 'curve':
$points = explode(' ', $value);
@list($start, $end, $point1, $point2) = $points;
list($start, $end, $point1, $point2) = array_pad($points, 4, null);
$points = array('start' => $start, 'end' => $end, 'point1' => $point1, 'point2' => $point2);
break;
}

View File

@ -18,7 +18,6 @@
namespace PhpOffice\PhpWord\Writer\Word2007\Part;
use PhpOffice\Common\XMLWriter;
use PhpOffice\PhpWord\Settings as PhpWordSettings;
use PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\Style\Font as FontStyle;
use PhpOffice\PhpWord\Style\Paragraph as ParagraphStyle;
@ -82,9 +81,10 @@ class Styles extends AbstractPart
*/
private function writeDefaultStyles(XMLWriter $xmlWriter, $styles)
{
$fontName = PhpWordSettings::getDefaultFontName();
$fontSize = PhpWordSettings::getDefaultFontSize();
$language = $this->getParentWriter()->getPhpWord()->getSettings()->getThemeFontLang();
$phpWord = $this->getParentWriter()->getPhpWord();
$fontName = $phpWord->getDefaultFontName();
$fontSize = $phpWord->getDefaultFontSize();
$language = $phpWord->getSettings()->getThemeFontLang();
$latinLanguage = ($language == null || $language->getLatin() === null) ? 'en-US' : $language->getLatin();
// Default font
@ -123,7 +123,18 @@ class Styles extends AbstractPart
$xmlWriter->writeAttribute('w:val', 'Normal');
$xmlWriter->endElement(); // w:name
if (isset($styles['Normal'])) {
$styleWriter = new ParagraphStyleWriter($xmlWriter, $styles['Normal']);
$normalStyle = $styles['Normal'];
// w:pPr
if ($normalStyle instanceof Fontstyle && $normalStyle->getParagraph() != null) {
$styleWriter = new ParagraphStyleWriter($xmlWriter, $normalStyle->getParagraph());
$styleWriter->write();
} elseif ($normalStyle instanceof ParagraphStyle) {
$styleWriter = new ParagraphStyleWriter($xmlWriter, $normalStyle);
$styleWriter->write();
}
// w:rPr
$styleWriter = new FontStyleWriter($xmlWriter, $normalStyle);
$styleWriter->write();
}
$xmlWriter->endElement(); // w:style

View File

@ -109,7 +109,7 @@ class Paragraph extends AbstractStyle
//Paragraph contextualSpacing
$xmlWriter->writeElementIf($styles['contextualSpacing'] === true, 'w:contextualSpacing');
//Paragraph contextualSpacing
//Paragraph textAlignment
$xmlWriter->writeElementIf($styles['textAlignment'] !== null, 'w:textAlignment', 'w:val', $styles['textAlignment']);
// Child style: alignment, indentation, spacing, and shading