Skip to content

Commit 99b04f0

Browse files
authored
fix reading of docx default style (#1238)
1 parent 4a530d1 commit 99b04f0

File tree

11 files changed

+115
-26
lines changed

11 files changed

+115
-26
lines changed

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ v0.15.0 (?? ??? 2018)
99
- Parsing of "align" HTML attribute - @troosan #1231
1010

1111
### Fixed
12+
- fix reading of docx default style - @troosan #1238
13+
14+
1215

1316
v0.14.0 (29 Dec 2017)
1417
----------------------
@@ -58,6 +61,8 @@ This version brings compatibility with PHP 7.0 & 7.1
5861
### Deprecated
5962
- PhpWord->getProtection(), get it from the settings instead PhpWord->getSettings()->getDocumentProtection();
6063

64+
65+
6166
v0.13.0 (31 July 2016)
6267
-------------------
6368
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
7782
- Improved error message for the case when `autoload.php` is not found. - @RomanSyroeshko #371
7883
- Renamed the `align` option of `NumberingLevel`, `Frame`, `Table`, and `Paragraph` styles into `alignment`. - @RomanSyroeshko
7984
- Improved performance of `TemplateProcessor::setValue()`. - @kazitanvirahsan #614, #617
80-
- Fixed some HTML tags not rendering any output (p, header & table) - #257, #324 - @twmobius and @garethellis
85+
- Fixed some HTML tags not rendering any output (p, header & table) - #257, #324 - @twmobius and @garethellis
8186

8287
### Deprecated
8388
- `getAlign` and `setAlign` methods of `NumberingLevel`, `Frame`, `Table`, and `Paragraph` styles.

docs/elements.rst

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ Parameters:
160160
- ``$text``. Text that appears in the document.
161161
- ``$depth``. Depth of list item.
162162
- ``$fontStyle``. See :ref:`font-style`.
163-
- ``$listStyle``. List style of the current element TYPE\_NUMBER,
163+
- ``$listStyle``. List style of the current element TYPE\_NUMBER,
164164
TYPE\_ALPHANUM, TYPE\_BULLET\_FILLED, etc. See list of constants in PHPWord\\Style\\ListItem.
165165
- ``$paragraphStyle``. See :ref:`paragraph-style`.
166166

@@ -345,15 +345,14 @@ The footnote numbering can be controlled by setting the FootnoteProperties on th
345345
.. code-block:: php
346346
347347
$fp = new PhpWord\SimpleType\FootnoteProperties();
348-
//sets the position of the footnote (pageBottom (default), beneathText, sectEnd, docEnd)
348+
//sets the position of the footnote (pageBottom (default), beneathText, sectEnd, docEnd)
349349
$fp->setPos(FootnoteProperties::POSITION_DOC_END);
350350
//set the number format to use (decimal (default), upperRoman, upperLetter, ...)
351351
$fp->setNumFmt(FootnoteProperties::NUMBER_FORMAT_LOWER_ROMAN);
352352
//force starting at other than 1
353353
$fp->setNumStart(2);
354354
//when to restart counting (continuous (default), eachSect, eachPage)
355355
$fp->setNumRestart(FootnoteProperties::RESTART_NUMBER_EACH_PAGE);
356-
357356
//And finaly, set it on the Section
358357
$section->setFootnoteProperties($properties);
359358
@@ -379,7 +378,7 @@ To be completed
379378
Fields
380379
------
381380

382-
Currently the following fields are supported:
381+
Currently the following fields are supported:
383382

384383
- PAGE
385384
- NUMPAGES

docs/general.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,6 @@ Use mirror margins to set up facing pages for double-sided documents, such as bo
167167
168168
$phpWord->getSettings()->setMirrorMargins(true);
169169
170-
171170
Spelling and grammatical checks
172171
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
173172

@@ -191,7 +190,7 @@ You can also specify the status of the spell and grammar checks, marking spellin
191190
192191
Track Revisions
193192
~~~~~~~~~~~~~~~
194-
Track changes can be activated using ``setTrackRevisions``, you can furture specify
193+
Track changes can be activated using ``setTrackRevisions``, you can furture specify
195194

196195
- Not to use move syntax, instead moved items will be seen as deleted in one place and added in another
197196
- Not track formatting revisions

docs/installing.rst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ Example:
5151
}
5252
}
5353
54-
5554
Using samples
5655
-------------
5756

src/PhpWord/Reader/Word2007/AbstractPart.php

Lines changed: 61 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ protected function readParagraphStyle(XMLReader $xmlReader, \DOMElement $domNode
307307

308308
$styleNode = $xmlReader->getElement('w:pPr', $domNode);
309309
$styleDefs = array(
310-
'styleName' => array(self::READ_VALUE, 'w:pStyle'),
310+
'styleName' => array(self::READ_VALUE, array('w:pStyle', 'w:name')),
311311
'alignment' => array(self::READ_VALUE, 'w:jc'),
312312
'basedOn' => array(self::READ_VALUE, 'w:basedOn'),
313313
'next' => array(self::READ_VALUE, 'w:next'),
@@ -349,9 +349,9 @@ protected function readFontStyle(XMLReader $xmlReader, \DOMElement $domNode)
349349
$styleNode = $xmlReader->getElement('w:rPr', $domNode);
350350
$styleDefs = array(
351351
'styleName' => array(self::READ_VALUE, 'w:rStyle'),
352-
'name' => array(self::READ_VALUE, 'w:rFonts', 'w:ascii'),
352+
'name' => array(self::READ_VALUE, 'w:rFonts', array('w:ascii', 'w:hAnsi', 'w:eastAsia', 'w:cs')),
353353
'hint' => array(self::READ_VALUE, 'w:rFonts', 'w:hint'),
354-
'size' => array(self::READ_SIZE, 'w:sz'),
354+
'size' => array(self::READ_SIZE, array('w:sz', 'w:szCs')),
355355
'color' => array(self::READ_VALUE, 'w:color'),
356356
'underline' => array(self::READ_VALUE, 'w:u'),
357357
'bold' => array(self::READ_TRUE, 'w:b'),
@@ -364,9 +364,7 @@ protected function readFontStyle(XMLReader $xmlReader, \DOMElement $domNode)
364364
'subScript' => array(self::READ_EQUAL, 'w:vertAlign', 'w:val', 'subscript'),
365365
'fgColor' => array(self::READ_VALUE, 'w:highlight'),
366366
'rtl' => array(self::READ_TRUE, 'w:rtl'),
367-
'font-latin' => array(self::READ_VALUE, 'w:font', 'w:val'),
368-
'font-eastAsia' => array(self::READ_VALUE, 'w:font', 'w:eastAsia'),
369-
'font-bidi' => array(self::READ_VALUE, 'w:font', 'w:bidi'),
367+
'lang' => array(self::READ_VALUE, 'w:lang'),
370368
);
371369

372370
return $this->readStyleDefs($xmlReader, $styleNode, $styleDefs);
@@ -400,6 +398,7 @@ protected function readTableStyle(XMLReader $xmlReader, \DOMElement $domNode)
400398
$ucfSide = ucfirst($side);
401399
$styleDefs["border{$ucfSide}Size"] = array(self::READ_VALUE, "w:tblBorders/w:$side", 'w:sz');
402400
$styleDefs["border{$ucfSide}Color"] = array(self::READ_VALUE, "w:tblBorders/w:$side", 'w:color');
401+
$styleDefs["border{$ucfSide}Style"] = array(self::READ_VALUE, "w:tblBorders/w:$side", 'w:val');
403402
}
404403
$style = $this->readStyleDefs($xmlReader, $styleNode, $styleDefs);
405404
}
@@ -428,6 +427,54 @@ private function readCellStyle(XMLReader $xmlReader, \DOMElement $domNode)
428427
return $this->readStyleDefs($xmlReader, $domNode, $styleDefs);
429428
}
430429

430+
/**
431+
* Returns the first child element found
432+
*
433+
* @param XMLReader $xmlReader
434+
* @param \DOMElement $parentNode
435+
* @param string|array $elements
436+
* @return string|null
437+
*/
438+
private function findPossibleElement(XMLReader $xmlReader, \DOMElement $parentNode = null, $elements)
439+
{
440+
if (is_array($elements)) {
441+
//if element is an array, we take the first element that exists in the XML
442+
foreach ($elements as $possibleElement) {
443+
if ($xmlReader->elementExists($possibleElement, $parentNode)) {
444+
return $possibleElement;
445+
}
446+
}
447+
} else {
448+
return $elements;
449+
}
450+
451+
return null;
452+
}
453+
454+
/**
455+
* Returns the first attribute found
456+
*
457+
* @param XMLReader $xmlReader
458+
* @param \DOMElement $node
459+
* @param string|array $attributes
460+
* @return string|null
461+
*/
462+
private function findPossibleAttribute(XMLReader $xmlReader, \DOMElement $node, $attributes)
463+
{
464+
//if attribute is an array, we take the first attribute that exists in the XML
465+
if (is_array($attributes)) {
466+
foreach ($attributes as $possibleAttribute) {
467+
if ($xmlReader->getAttribute($possibleAttribute, $node)) {
468+
return $possibleAttribute;
469+
}
470+
}
471+
} else {
472+
return $attributes;
473+
}
474+
475+
return null;
476+
}
477+
431478
/**
432479
* Read style definition
433480
*
@@ -442,11 +489,18 @@ protected function readStyleDefs(XMLReader $xmlReader, \DOMElement $parentNode =
442489
$styles = array();
443490

444491
foreach ($styleDefs as $styleProp => $styleVal) {
445-
@list($method, $element, $attribute, $expected) = $styleVal;
492+
list($method, $element, $attribute, $expected) = array_pad($styleVal, 4, null);
493+
494+
$element = $this->findPossibleElement($xmlReader, $parentNode, $element);
495+
if ($element === null) {
496+
continue;
497+
}
446498

447499
if ($xmlReader->elementExists($element, $parentNode)) {
448500
$node = $xmlReader->getElement($element, $parentNode);
449501

502+
$attribute = $this->findPossibleAttribute($xmlReader, $node, $attribute);
503+
450504
// Use w:val as default if no attribute assigned
451505
$attribute = ($attribute === null) ? 'w:val' : $attribute;
452506
$attributeValue = $xmlReader->getAttribute($attribute, $node);

src/PhpWord/Reader/Word2007/Settings.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ protected function setThemeFontLang(XMLReader $xmlReader, PhpWord $phpWord, \DOM
8080

8181
$themeFontLang = new Language();
8282
$themeFontLang->setLatin($val);
83-
$themeFontLang->setLatin($eastAsia);
84-
$themeFontLang->setLatin($bidi);
83+
$themeFontLang->setEastAsia($eastAsia);
84+
$themeFontLang->setBidirectional($bidi);
8585

8686
$phpWord->getSettings()->setThemeFontLang($themeFontLang);
8787
}

src/PhpWord/Reader/Word2007/Styles.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
use PhpOffice\Common\XMLReader;
2121
use PhpOffice\PhpWord\PhpWord;
22+
use PhpOffice\PhpWord\Style\Language;
2223

2324
/**
2425
* Styles reader
@@ -37,6 +38,28 @@ public function read(PhpWord $phpWord)
3738
$xmlReader = new XMLReader();
3839
$xmlReader->getDomFromZip($this->docFile, $this->xmlFile);
3940

41+
$fontDefaults = $xmlReader->getElement('w:docDefaults/w:rPrDefault');
42+
if ($fontDefaults !== null) {
43+
$fontDefaultStyle = $this->readFontStyle($xmlReader, $fontDefaults);
44+
if (array_key_exists('name', $fontDefaultStyle)) {
45+
$phpWord->setDefaultFontName($fontDefaultStyle['name']);
46+
}
47+
if (array_key_exists('size', $fontDefaultStyle)) {
48+
$phpWord->setDefaultFontSize($fontDefaultStyle['size']);
49+
}
50+
if (array_key_exists('lang', $fontDefaultStyle)) {
51+
$phpWord->getSettings()->setThemeFontLang(new Language($fontDefaultStyle['lang']));
52+
}
53+
}
54+
55+
$paragraphDefaults = $xmlReader->getElement('w:docDefaults/w:pPrDefault');
56+
if ($paragraphDefaults !== null) {
57+
$paragraphDefaultStyle = $this->readParagraphStyle($xmlReader, $paragraphDefaults);
58+
if ($paragraphDefaultStyle != null) {
59+
$phpWord->setDefaultParagraphStyle();
60+
}
61+
}
62+
4063
$nodes = $xmlReader->getElements('w:style');
4164
if ($nodes->length > 0) {
4265
foreach ($nodes as $node) {

src/PhpWord/Style/Paragraph.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
use PhpOffice\Common\Text;
2121
use PhpOffice\PhpWord\Exception\InvalidStyleException;
2222
use PhpOffice\PhpWord\SimpleType\Jc;
23-
use PhpOffice\PhpWord\SimpleType\LineSpacingRule;
2423
use PhpOffice\PhpWord\SimpleType\TextAlignment;
2524

2625
/**

src/PhpWord/Writer/Word2007/Element/Shape.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,12 @@ private function getPoints($type, $value)
154154
case 'arc':
155155
case 'line':
156156
$points = explode(' ', $value);
157-
@list($start, $end) = $points;
157+
list($start, $end) = array_pad($points, 2, null);
158158
$points = array('start' => $start, 'end' => $end);
159159
break;
160160
case 'curve':
161161
$points = explode(' ', $value);
162-
@list($start, $end, $point1, $point2) = $points;
162+
list($start, $end, $point1, $point2) = array_pad($points, 4, null);
163163
$points = array('start' => $start, 'end' => $end, 'point1' => $point1, 'point2' => $point2);
164164
break;
165165
}

src/PhpWord/Writer/Word2007/Part/Styles.php

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
namespace PhpOffice\PhpWord\Writer\Word2007\Part;
1919

2020
use PhpOffice\Common\XMLWriter;
21-
use PhpOffice\PhpWord\Settings as PhpWordSettings;
2221
use PhpOffice\PhpWord\Style;
2322
use PhpOffice\PhpWord\Style\Font as FontStyle;
2423
use PhpOffice\PhpWord\Style\Paragraph as ParagraphStyle;
@@ -82,9 +81,10 @@ public function write()
8281
*/
8382
private function writeDefaultStyles(XMLWriter $xmlWriter, $styles)
8483
{
85-
$fontName = PhpWordSettings::getDefaultFontName();
86-
$fontSize = PhpWordSettings::getDefaultFontSize();
87-
$language = $this->getParentWriter()->getPhpWord()->getSettings()->getThemeFontLang();
84+
$phpWord = $this->getParentWriter()->getPhpWord();
85+
$fontName = $phpWord->getDefaultFontName();
86+
$fontSize = $phpWord->getDefaultFontSize();
87+
$language = $phpWord->getSettings()->getThemeFontLang();
8888
$latinLanguage = ($language == null || $language->getLatin() === null) ? 'en-US' : $language->getLatin();
8989

9090
// Default font
@@ -123,7 +123,18 @@ private function writeDefaultStyles(XMLWriter $xmlWriter, $styles)
123123
$xmlWriter->writeAttribute('w:val', 'Normal');
124124
$xmlWriter->endElement(); // w:name
125125
if (isset($styles['Normal'])) {
126-
$styleWriter = new ParagraphStyleWriter($xmlWriter, $styles['Normal']);
126+
$normalStyle = $styles['Normal'];
127+
// w:pPr
128+
if ($normalStyle instanceof Fontstyle && $normalStyle->getParagraph() != null) {
129+
$styleWriter = new ParagraphStyleWriter($xmlWriter, $normalStyle->getParagraph());
130+
$styleWriter->write();
131+
} elseif ($normalStyle instanceof ParagraphStyle) {
132+
$styleWriter = new ParagraphStyleWriter($xmlWriter, $normalStyle);
133+
$styleWriter->write();
134+
}
135+
136+
// w:rPr
137+
$styleWriter = new FontStyleWriter($xmlWriter, $normalStyle);
127138
$styleWriter->write();
128139
}
129140
$xmlWriter->endElement(); // w:style

0 commit comments

Comments
 (0)