Skip to content

Commit 61c6d51

Browse files
committed
Refactor Word2007 reader
1 parent f536bd6 commit 61c6d51

File tree

4 files changed

+196
-171
lines changed

4 files changed

+196
-171
lines changed

src/PhpWord/Reader/ODText/AbstractPart.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,20 @@
2525
*/
2626
abstract class AbstractPart extends Word2007AbstractPart
2727
{
28+
/**
29+
* Read w:p (override)
30+
*
31+
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
32+
* @param \DOMElement $domNode
33+
* @param mixed $parent
34+
* @param string $docPart
35+
*
36+
* @todo Get font style for preserve text
37+
*/
38+
protected function readParagraph(XMLReader $xmlReader, \DOMElement $domNode, &$parent, $docPart)
39+
{
40+
}
41+
2842
/**
2943
* Read w:r (override)
3044
*
@@ -38,6 +52,18 @@ protected function readRun(XMLReader $xmlReader, \DOMElement $domNode, &$parent,
3852
{
3953
}
4054

55+
/**
56+
* Read w:tbl (override)
57+
*
58+
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
59+
* @param \DOMElement $domNode
60+
* @param mixed $parent
61+
* @param string $docPart
62+
*/
63+
protected function readTable(XMLReader $xmlReader, \DOMElement $domNode, &$parent, $docPart)
64+
{
65+
}
66+
4167
/**
4268
* Read w:pPr (override)
4369
*/

src/PhpWord/Reader/Word2007/AbstractPart.php

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,96 @@ public function setRels($value)
8686
$this->rels = $value;
8787
}
8888

89+
/**
90+
* Read w:p
91+
*
92+
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
93+
* @param \DOMElement $domNode
94+
* @param mixed $parent
95+
* @param string $docPart
96+
*
97+
* @todo Get font style for preserve text
98+
*/
99+
protected function readParagraph(XMLReader $xmlReader, \DOMElement $domNode, &$parent, $docPart)
100+
{
101+
// Paragraph style
102+
$paragraphStyle = null;
103+
$headingMatches = array();
104+
if ($xmlReader->elementExists('w:pPr', $domNode)) {
105+
$paragraphStyle = $this->readParagraphStyle($xmlReader, $domNode);
106+
if (is_array($paragraphStyle) && array_key_exists('styleName', $paragraphStyle)) {
107+
preg_match('/Heading(\d)/', $paragraphStyle['styleName'], $headingMatches);
108+
}
109+
}
110+
111+
// PreserveText
112+
if ($xmlReader->elementExists('w:r/w:instrText', $domNode)) {
113+
$ignoreText = false;
114+
$textContent = '';
115+
$fontStyle = $this->readFontStyle($xmlReader, $domNode);
116+
$nodes = $xmlReader->getElements('w:r', $domNode);
117+
foreach ($nodes as $node) {
118+
$instrText = $xmlReader->getValue('w:instrText', $node);
119+
if ($xmlReader->elementExists('w:fldChar', $node)) {
120+
$fldCharType = $xmlReader->getAttribute('w:fldCharType', $node, 'w:fldChar');
121+
if ($fldCharType == 'begin') {
122+
$ignoreText = true;
123+
} elseif ($fldCharType == 'end') {
124+
$ignoreText = false;
125+
}
126+
}
127+
if (!is_null($instrText)) {
128+
$textContent .= '{' . $instrText . '}';
129+
} else {
130+
if ($ignoreText === false) {
131+
$textContent .= $xmlReader->getValue('w:t', $node);
132+
}
133+
}
134+
}
135+
$parent->addPreserveText($textContent, $fontStyle, $paragraphStyle);
136+
137+
// List item
138+
} elseif ($xmlReader->elementExists('w:pPr/w:numPr', $domNode)) {
139+
$textContent = '';
140+
$numId = $xmlReader->getAttribute('w:val', $domNode, 'w:pPr/w:numPr/w:numId');
141+
$levelId = $xmlReader->getAttribute('w:val', $domNode, 'w:pPr/w:numPr/w:ilvl');
142+
$nodes = $xmlReader->getElements('w:r', $domNode);
143+
foreach ($nodes as $node) {
144+
$textContent .= $xmlReader->getValue('w:t', $node);
145+
}
146+
$parent->addListItem($textContent, $levelId, null, "PHPWordList{$numId}", $paragraphStyle);
147+
148+
// Heading
149+
} elseif (!empty($headingMatches)) {
150+
$textContent = '';
151+
$nodes = $xmlReader->getElements('w:r', $domNode);
152+
foreach ($nodes as $node) {
153+
$textContent .= $xmlReader->getValue('w:t', $node);
154+
}
155+
$parent->addTitle($textContent, $headingMatches[1]);
156+
157+
// Text and TextRun
158+
} else {
159+
$runCount = $xmlReader->countElements('w:r', $domNode);
160+
$linkCount = $xmlReader->countElements('w:hyperlink', $domNode);
161+
$runLinkCount = $runCount + $linkCount;
162+
if ($runLinkCount == 0) {
163+
$parent->addTextBreak(null, $paragraphStyle);
164+
} else {
165+
if ($runLinkCount > 1) {
166+
$textrun = $parent->addTextRun($paragraphStyle);
167+
$textParent = &$textrun;
168+
} else {
169+
$textParent = &$parent;
170+
}
171+
$nodes = $xmlReader->getElements('*', $domNode);
172+
foreach ($nodes as $node) {
173+
$this->readRun($xmlReader, $node, $textParent, $docPart, $paragraphStyle);
174+
}
175+
}
176+
}
177+
}
178+
89179
/**
90180
* Read w:r
91181
*
@@ -148,6 +238,66 @@ protected function readRun(XMLReader $xmlReader, \DOMElement $domNode, &$parent,
148238
}
149239
}
150240

241+
/**
242+
* Read w:tbl
243+
*
244+
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
245+
* @param \DOMElement $domNode
246+
* @param mixed $parent
247+
* @param string $docPart
248+
*/
249+
protected function readTable(XMLReader $xmlReader, \DOMElement $domNode, &$parent, $docPart)
250+
{
251+
// Table style
252+
$tblStyle = null;
253+
if ($xmlReader->elementExists('w:tblPr', $domNode)) {
254+
$tblStyle = $this->readTableStyle($xmlReader, $domNode);
255+
}
256+
257+
/** @var \PhpOffice\PhpWord\Element\Table $table Type hint */
258+
$table = $parent->addTable($tblStyle);
259+
$tblNodes = $xmlReader->getElements('*', $domNode);
260+
foreach ($tblNodes as $tblNode) {
261+
if ($tblNode->nodeName == 'w:tblGrid') { // Column
262+
// @todo Do something with table columns
263+
264+
} elseif ($tblNode->nodeName == 'w:tr') { // Row
265+
$rowHeight = $xmlReader->getAttribute('w:val', $tblNode, 'w:trPr/w:trHeight');
266+
$rowHRule = $xmlReader->getAttribute('w:hRule', $tblNode, 'w:trPr/w:trHeight');
267+
$rowHRule = $rowHRule == 'exact' ? true : false;
268+
$rowStyle = array(
269+
'tblHeader' => $xmlReader->elementExists('w:trPr/w:tblHeader', $tblNode),
270+
'cantSplit' => $xmlReader->elementExists('w:trPr/w:cantSplit', $tblNode),
271+
'exactHeight' => $rowHRule,
272+
);
273+
274+
$row = $table->addRow($rowHeight, $rowStyle);
275+
$rowNodes = $xmlReader->getElements('*', $tblNode);
276+
foreach ($rowNodes as $rowNode) {
277+
if ($rowNode->nodeName == 'w:trPr') { // Row style
278+
// @todo Do something with row style
279+
280+
} elseif ($rowNode->nodeName == 'w:tc') { // Cell
281+
$cellWidth = $xmlReader->getAttribute('w:w', $rowNode, 'w:tcPr/w:tcW');
282+
$cellStyle = null;
283+
$cellStyleNode = $xmlReader->getElement('w:tcPr', $rowNode);
284+
if (!is_null($cellStyleNode)) {
285+
$cellStyle = $this->readCellStyle($xmlReader, $cellStyleNode);
286+
}
287+
288+
$cell = $row->addCell($cellWidth, $cellStyle);
289+
$cellNodes = $xmlReader->getElements('*', $rowNode);
290+
foreach ($cellNodes as $cellNode) {
291+
if ($cellNode->nodeName == 'w:p') { // Paragraph
292+
$this->readParagraph($xmlReader, $cellNode, $cell, $docPart);
293+
}
294+
}
295+
}
296+
}
297+
}
298+
}
299+
}
300+
151301
/**
152302
* Read w:pPr
153303
*
@@ -258,6 +408,26 @@ protected function readTableStyle(XMLReader $xmlReader, \DOMElement $domNode)
258408
return $style;
259409
}
260410

411+
/**
412+
* Read w:tcPr
413+
*
414+
* @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
415+
* @param \DOMElement $domNode
416+
* @return array
417+
*/
418+
private function readCellStyle(XMLReader $xmlReader, \DOMElement $domNode)
419+
{
420+
$styleDefs = array(
421+
'valign' => array(self::READ_VALUE, 'w:vAlign'),
422+
'textDirection' => array(self::READ_VALUE, 'w:textDirection'),
423+
'gridSpan' => array(self::READ_VALUE, 'w:gridSpan'),
424+
'vMerge' => array(self::READ_VALUE, 'w:vMerge'),
425+
'bgColor' => array(self::READ_VALUE, 'w:shd/w:fill'),
426+
);
427+
428+
return $this->readStyleDefs($xmlReader, $domNode, $styleDefs);
429+
}
430+
261431
/**
262432
* Read style definition
263433
*

0 commit comments

Comments
 (0)