@@ -86,6 +86,96 @@ public function setRels($value)
86
86
$ this ->rels = $ value ;
87
87
}
88
88
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
+
89
179
/**
90
180
* Read w:r
91
181
*
@@ -148,6 +238,66 @@ protected function readRun(XMLReader $xmlReader, \DOMElement $domNode, &$parent,
148
238
}
149
239
}
150
240
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
+
151
301
/**
152
302
* Read w:pPr
153
303
*
@@ -258,6 +408,26 @@ protected function readTableStyle(XMLReader $xmlReader, \DOMElement $domNode)
258
408
return $ style ;
259
409
}
260
410
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
+
261
431
/**
262
432
* Read style definition
263
433
*
0 commit comments