|
18 | 18 | namespace PhpOffice\PhpWord\Reader\Word2007;
|
19 | 19 |
|
20 | 20 | use PhpOffice\Common\XMLReader;
|
| 21 | +use PhpOffice\PhpWord\Element\AbstractContainer; |
21 | 22 | use PhpOffice\PhpWord\Element\TextRun;
|
22 | 23 | use PhpOffice\PhpWord\Element\TrackChange;
|
23 | 24 | use PhpOffice\PhpWord\PhpWord;
|
@@ -161,20 +162,14 @@ protected function readParagraph(XMLReader $xmlReader, \DOMElement $domNode, $pa
|
161 | 162 | $parent->addTitle($textContent, $headingDepth);
|
162 | 163 | } else {
|
163 | 164 | // Text and TextRun
|
164 |
| - $runCount = $xmlReader->countElements('w:r', $domNode); |
165 |
| - $insCount = $xmlReader->countElements('w:ins', $domNode); |
166 |
| - $delCount = $xmlReader->countElements('w:del', $domNode); |
167 |
| - $linkCount = $xmlReader->countElements('w:hyperlink', $domNode); |
168 |
| - $runLinkCount = $runCount + $insCount + $delCount + $linkCount; |
169 |
| - if (0 == $runLinkCount) { |
| 165 | + $textRunContainers = $xmlReader->countElements('w:r|w:ins|w:del|w:hyperlink|w:smartTag', $domNode); |
| 166 | + if (0 === $textRunContainers) { |
170 | 167 | $parent->addTextBreak(null, $paragraphStyle);
|
171 | 168 | } else {
|
172 | 169 | $nodes = $xmlReader->getElements('*', $domNode);
|
173 |
| - if ($runLinkCount > 1) { |
174 |
| - $parent = $parent->addTextRun($paragraphStyle); |
175 |
| - } |
| 170 | + $paragraph = $parent->addTextRun($paragraphStyle); |
176 | 171 | foreach ($nodes as $node) {
|
177 |
| - $this->readRun($xmlReader, $node, $parent, $docPart, $paragraphStyle); |
| 172 | + $this->readRun($xmlReader, $node, $paragraph, $docPart, $paragraphStyle); |
178 | 173 | }
|
179 | 174 | }
|
180 | 175 | }
|
@@ -216,75 +211,85 @@ private function getHeadingDepth(array $paragraphStyle = null)
|
216 | 211 | */
|
217 | 212 | protected function readRun(XMLReader $xmlReader, \DOMElement $domNode, $parent, $docPart, $paragraphStyle = null)
|
218 | 213 | {
|
219 |
| - if (in_array($domNode->nodeName, array('w:ins', 'w:del'))) { |
| 214 | + if (in_array($domNode->nodeName, array('w:ins', 'w:del', 'w:smartTag', 'w:hyperlink'))) { |
220 | 215 | $nodes = $xmlReader->getElements('*', $domNode);
|
221 | 216 | foreach ($nodes as $node) {
|
222 |
| - return $this->readRun($xmlReader, $node, $parent, $docPart, $paragraphStyle); |
| 217 | + $this->readRun($xmlReader, $node, $parent, $docPart, $paragraphStyle); |
| 218 | + } |
| 219 | + } elseif ($domNode->nodeName == 'w:r') { |
| 220 | + $fontStyle = $this->readFontStyle($xmlReader, $domNode); |
| 221 | + $nodes = $xmlReader->getElements('*', $domNode); |
| 222 | + foreach ($nodes as $node) { |
| 223 | + $this->readRunChild($xmlReader, $node, $parent, $docPart, $paragraphStyle, $fontStyle); |
223 | 224 | }
|
224 | 225 | }
|
| 226 | + } |
225 | 227 |
|
226 |
| - if (!in_array($domNode->nodeName, array('w:r', 'w:hyperlink'))) { |
227 |
| - return; |
228 |
| - } |
229 |
| - $fontStyle = $this->readFontStyle($xmlReader, $domNode); |
230 |
| - |
231 |
| - // Link |
232 |
| - if ('w:hyperlink' == $domNode->nodeName) { |
233 |
| - $rId = $xmlReader->getAttribute('r:id', $domNode); |
234 |
| - $textContent = $xmlReader->getValue('w:r/w:t', $domNode); |
| 228 | + /** |
| 229 | + * Parses nodes under w:r |
| 230 | + * |
| 231 | + * @param XMLReader $xmlReader |
| 232 | + * @param \DOMElement $node |
| 233 | + * @param AbstractContainer $parent |
| 234 | + * @param string $docPart |
| 235 | + * @param mixed $paragraphStyle |
| 236 | + * @param mixed $fontStyle |
| 237 | + */ |
| 238 | + protected function readRunChild(XMLReader $xmlReader, \DOMElement $node, AbstractContainer $parent, $docPart, $paragraphStyle = null, $fontStyle = null) |
| 239 | + { |
| 240 | + $runParent = $node->parentNode->parentNode; |
| 241 | + if ($node->nodeName == 'w:footnoteReference') { |
| 242 | + // Footnote |
| 243 | + $wId = $xmlReader->getAttribute('w:id', $node); |
| 244 | + $footnote = $parent->addFootnote(); |
| 245 | + $footnote->setRelationId($wId); |
| 246 | + } elseif ($node->nodeName == 'w:endnoteReference') { |
| 247 | + // Endnote |
| 248 | + $wId = $xmlReader->getAttribute('w:id', $node); |
| 249 | + $endnote = $parent->addEndnote(); |
| 250 | + $endnote->setRelationId($wId); |
| 251 | + } elseif ($node->nodeName == 'w:pict') { |
| 252 | + // Image |
| 253 | + $rId = $xmlReader->getAttribute('r:id', $node, 'v:shape/v:imagedata'); |
235 | 254 | $target = $this->getMediaTarget($docPart, $rId);
|
236 | 255 | if (!is_null($target)) {
|
237 |
| - $parent->addLink($target, $textContent, $fontStyle, $paragraphStyle); |
238 |
| - } |
239 |
| - } else { |
240 |
| - if ($xmlReader->elementExists('w:footnoteReference', $domNode)) { |
241 |
| - // Footnote |
242 |
| - $wId = $xmlReader->getAttribute('w:id', $domNode, 'w:footnoteReference'); |
243 |
| - $footnote = $parent->addFootnote(); |
244 |
| - $footnote->setRelationId($wId); |
245 |
| - } elseif ($xmlReader->elementExists('w:endnoteReference', $domNode)) { |
246 |
| - // Endnote |
247 |
| - $wId = $xmlReader->getAttribute('w:id', $domNode, 'w:endnoteReference'); |
248 |
| - $endnote = $parent->addEndnote(); |
249 |
| - $endnote->setRelationId($wId); |
250 |
| - } elseif ($xmlReader->elementExists('w:pict', $domNode)) { |
251 |
| - // Image |
252 |
| - $rId = $xmlReader->getAttribute('r:id', $domNode, 'w:pict/v:shape/v:imagedata'); |
253 |
| - $target = $this->getMediaTarget($docPart, $rId); |
254 |
| - if (!is_null($target)) { |
255 |
| - if ('External' == $this->getTargetMode($docPart, $rId)) { |
256 |
| - $imageSource = $target; |
257 |
| - } else { |
258 |
| - $imageSource = "zip://{$this->docFile}#{$target}"; |
259 |
| - } |
260 |
| - $parent->addImage($imageSource); |
261 |
| - } |
262 |
| - } elseif ($xmlReader->elementExists('w:object', $domNode)) { |
263 |
| - // Object |
264 |
| - $rId = $xmlReader->getAttribute('r:id', $domNode, 'w:object/o:OLEObject'); |
265 |
| - // $rIdIcon = $xmlReader->getAttribute('r:id', $domNode, 'w:object/v:shape/v:imagedata'); |
266 |
| - $target = $this->getMediaTarget($docPart, $rId); |
267 |
| - if (!is_null($target)) { |
268 |
| - $textContent = "<Object: {$target}>"; |
269 |
| - $parent->addText($textContent, $fontStyle, $paragraphStyle); |
| 256 | + if ('External' == $this->getTargetMode($docPart, $rId)) { |
| 257 | + $imageSource = $target; |
| 258 | + } else { |
| 259 | + $imageSource = "zip://{$this->docFile}#{$target}"; |
270 | 260 | }
|
| 261 | + $parent->addImage($imageSource); |
271 | 262 | }
|
272 |
| - if ($xmlReader->elementExists('w:br', $domNode)) { |
273 |
| - $parent->addTextBreak(); |
| 263 | + } elseif ($node->nodeName == 'w:object') { |
| 264 | + // Object |
| 265 | + $rId = $xmlReader->getAttribute('r:id', $node, 'o:OLEObject'); |
| 266 | + // $rIdIcon = $xmlReader->getAttribute('r:id', $domNode, 'w:object/v:shape/v:imagedata'); |
| 267 | + $target = $this->getMediaTarget($docPart, $rId); |
| 268 | + if (!is_null($target)) { |
| 269 | + $textContent = "<Object: {$target}>"; |
| 270 | + $parent->addText($textContent, $fontStyle, $paragraphStyle); |
274 | 271 | }
|
275 |
| - if ($xmlReader->elementExists('w:t', $domNode)) { |
276 |
| - // TextRun |
277 |
| - if ($domNode->parentNode->nodeName == 'w:del') { |
278 |
| - $textContent = $xmlReader->getValue('w:delText', $domNode); |
279 |
| - } else { |
280 |
| - $textContent = $xmlReader->getValue('w:t', $domNode); |
| 272 | + } elseif ($node->nodeName == 'w:br') { |
| 273 | + $parent->addTextBreak(); |
| 274 | + } elseif ($node->nodeName == 'w:tab') { |
| 275 | + $parent->addText("\t"); |
| 276 | + } elseif ($node->nodeName == 'w:t' || $node->nodeName == 'w:delText') { |
| 277 | + // TextRun |
| 278 | + $textContent = $xmlReader->getValue('.', $node); |
| 279 | + |
| 280 | + if ($runParent->nodeName == 'w:hyperlink') { |
| 281 | + $rId = $xmlReader->getAttribute('r:id', $runParent); |
| 282 | + $target = $this->getMediaTarget($docPart, $rId); |
| 283 | + if (!is_null($target)) { |
| 284 | + $parent->addLink($target, $textContent, $fontStyle, $paragraphStyle); |
281 | 285 | }
|
| 286 | + } else { |
282 | 287 | /** @var AbstractElement $element */
|
283 | 288 | $element = $parent->addText($textContent, $fontStyle, $paragraphStyle);
|
284 |
| - if (in_array($domNode->parentNode->nodeName, array('w:ins', 'w:del'))) { |
285 |
| - $type = ($domNode->parentNode->nodeName == 'w:del') ? TrackChange::DELETED : TrackChange::INSERTED; |
286 |
| - $author = $domNode->parentNode->getAttribute('w:author'); |
287 |
| - $date = \DateTime::createFromFormat('Y-m-d\TH:i:s\Z', $domNode->parentNode->getAttribute('w:date')); |
| 289 | + if (in_array($runParent->nodeName, array('w:ins', 'w:del'))) { |
| 290 | + $type = ($runParent->nodeName == 'w:del') ? TrackChange::DELETED : TrackChange::INSERTED; |
| 291 | + $author = $runParent->getAttribute('w:author'); |
| 292 | + $date = \DateTime::createFromFormat('Y-m-d\TH:i:s\Z', $runParent->getAttribute('w:date')); |
288 | 293 | $element->setChangeInfo($type, $author, $date);
|
289 | 294 | }
|
290 | 295 | }
|
|
0 commit comments