Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
55 / 55
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
Text
100.00% covered (success)
100.00%
55 / 55
100.00% covered (success)
100.00%
3 / 3
23
100.00% covered (success)
100.00%
1 / 1
 write
100.00% covered (success)
100.00%
29 / 29
100.00% covered (success)
100.00%
1 / 1
13
 replacetabs
100.00% covered (success)
100.00%
20 / 20
100.00% covered (success)
100.00%
1 / 1
6
 writeChangeInsertion
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2/**
3 * This file is part of PHPWord - A pure PHP library for reading and writing
4 * word processing documents.
5 *
6 * PHPWord is free software distributed under the terms of the GNU Lesser
7 * General Public License version 3 as published by the Free Software Foundation.
8 *
9 * For the full copyright and license information, please read the LICENSE
10 * file that was distributed with this source code. For the full list of
11 * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
12 *
13 * @see         https://github.com/PHPOffice/PHPWord
14 *
15 * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
16 */
17
18namespace PhpOffice\PhpWord\Writer\ODText\Element;
19
20use PhpOffice\PhpWord\Element\TrackChange;
21use PhpOffice\PhpWord\Exception\Exception;
22
23/**
24 * Text element writer.
25 *
26 * @since 0.10.0
27 */
28class Text extends AbstractElement
29{
30    /**
31     * Write element.
32     */
33    public function write(): void
34    {
35        $xmlWriter = $this->getXmlWriter();
36        $element = $this->getElement();
37        if (!$element instanceof \PhpOffice\PhpWord\Element\Text) {
38            return;
39        }
40        $fontStyle = $element->getFontStyle();
41        $paragraphStyle = $element->getParagraphStyle();
42
43        // @todo Commented for TextRun. Should really checkout this value
44        // $fStyleIsObject = ($fontStyle instanceof Font) ? true : false;
45        //$fStyleIsObject = false;
46
47        //if ($fStyleIsObject) {
48        // Don't never be the case, because I browse all sections for cleaning all styles not declared
49        //    throw new Exception('PhpWord : $fStyleIsObject wouldn\'t be an object');
50        //}
51
52        if (!$this->withoutP) {
53            $xmlWriter->startElement('text:p'); // text:p
54        }
55        if ($element->getTrackChange() != null && $element->getTrackChange()->getChangeType() == TrackChange::DELETED) {
56            $xmlWriter->startElement('text:change');
57            $xmlWriter->writeAttribute('text:change-id', $element->getTrackChange()->getElementId());
58            $xmlWriter->endElement();
59        } else {
60            if (empty($paragraphStyle)) {
61                if (!$this->withoutP) {
62                    $xmlWriter->writeAttribute('text:style-name', 'Normal');
63                }
64            } elseif (is_string($paragraphStyle)) {
65                if (!$this->withoutP) {
66                    $xmlWriter->writeAttribute('text:style-name', $paragraphStyle);
67                }
68            }
69
70            if (!empty($fontStyle)) {
71                // text:span
72                $xmlWriter->startElement('text:span');
73                if (is_string($fontStyle)) {
74                    $xmlWriter->writeAttribute('text:style-name', $fontStyle);
75                }
76            }
77
78            $this->writeChangeInsertion(true, $element->getTrackChange());
79            $this->replaceTabs($element->getText(), $xmlWriter);
80            $this->writeChangeInsertion(false, $element->getTrackChange());
81
82            if (!empty($fontStyle)) {
83                $xmlWriter->endElement();
84            }
85        }
86        if (!$this->withoutP) {
87            $xmlWriter->endElement(); // text:p
88        }
89    }
90
91    private function replacetabs($text, $xmlWriter): void
92    {
93        if (preg_match('/^ +/', $text, $matches)) {
94            $num = strlen($matches[0]);
95            $xmlWriter->startElement('text:s');
96            $xmlWriter->writeAttributeIf($num > 1, 'text:c', "$num");
97            $xmlWriter->endElement();
98            $text = preg_replace('/^ +/', '', $text);
99        }
100        preg_match_all('/([\\s\\S]*?)(\\t|  +| ?$)/', $text, $matches, PREG_SET_ORDER);
101        foreach ($matches as $match) {
102            $this->writeText($match[1]);
103            if ($match[2] === '') {
104                break;
105            } elseif ($match[2] === "\t") {
106                $xmlWriter->writeElement('text:tab');
107            } elseif ($match[2] === ' ') {
108                $xmlWriter->writeElement('text:s');
109
110                break;
111            } else {
112                $num = strlen($match[2]);
113                $xmlWriter->startElement('text:s');
114                $xmlWriter->writeAttributeIf($num > 1, 'text:c', "$num");
115                $xmlWriter->endElement();
116            }
117        }
118    }
119
120    private function writeChangeInsertion($start = true, ?TrackChange $trackChange = null): void
121    {
122        if ($trackChange == null || $trackChange->getChangeType() != TrackChange::INSERTED) {
123            return;
124        }
125        $xmlWriter = $this->getXmlWriter();
126        $xmlWriter->startElement('text:change-' . ($start ? 'start' : 'end'));
127        $xmlWriter->writeAttribute('text:change-id', $trackChange->getElementId());
128        $xmlWriter->endElement();
129    }
130}