Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
98 / 98
100.00% covered (success)
100.00%
9 / 9
CRAP
100.00% covered (success)
100.00%
1 / 1
Text
100.00% covered (success)
100.00%
98 / 98
100.00% covered (success)
100.00%
9 / 9
37
100.00% covered (success)
100.00%
1 / 1
 write
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
3
 setOpeningText
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setClosingText
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 writeOpening
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 writeClosing
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 writeTrackChangeOpening
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
1 / 1
6
 writeTrackChangeClosing
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
4
 getParagraphStyle
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
6
 processFontStyle
100.00% covered (success)
100.00%
26 / 26
100.00% covered (success)
100.00%
1 / 1
12
1<?php
2
3/**
4 * This file is part of PHPWord - A pure PHP library for reading and writing
5 * word processing documents.
6 *
7 * PHPWord is free software distributed under the terms of the GNU Lesser
8 * General Public License version 3 as published by the Free Software Foundation.
9 *
10 * For the full copyright and license information, please read the LICENSE
11 * file that was distributed with this source code. For the full list of
12 * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
13 *
14 * @see         https://github.com/PHPOffice/PHPWord
15 *
16 * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
17 */
18
19namespace PhpOffice\PhpWord\Writer\HTML\Element;
20
21use PhpOffice\PhpWord\Element\TrackChange;
22use PhpOffice\PhpWord\Style;
23use PhpOffice\PhpWord\Style\Font;
24use PhpOffice\PhpWord\Style\Paragraph;
25use PhpOffice\PhpWord\Writer\HTML;
26use PhpOffice\PhpWord\Writer\HTML\Style\Font as FontStyleWriter;
27use PhpOffice\PhpWord\Writer\HTML\Style\Paragraph as ParagraphStyleWriter;
28
29/**
30 * Text element HTML writer.
31 *
32 * @since 0.10.0
33 */
34class Text extends AbstractElement
35{
36    /**
37     * Text written after opening.
38     *
39     * @var string
40     */
41    private $openingText = '';
42
43    /**
44     * Text written before closing.
45     *
46     * @var string
47     */
48    private $closingText = '';
49
50    /**
51     * Opening tags.
52     *
53     * @var string
54     */
55    private $openingTags = '';
56
57    /**
58     * Closing tag.
59     *
60     * @var string
61     */
62    private $closingTags = '';
63
64    /**
65     * Write text.
66     *
67     * @return string
68     */
69    public function write()
70    {
71        $this->processFontStyle();
72
73        /** @var \PhpOffice\PhpWord\Element\Text $element Type hint */
74        $element = $this->element;
75
76        $text = $this->parentWriter->escapeHTML($element->getText());
77        if (!$this->withoutP && !trim($text)) {
78            $text = '&nbsp;';
79        }
80
81        $content = '';
82        $content .= $this->writeOpening();
83        $content .= $this->openingText;
84        $content .= $this->openingTags;
85        $content .= $text;
86        $content .= $this->closingTags;
87        $content .= $this->closingText;
88        $content .= $this->writeClosing();
89
90        return $content;
91    }
92
93    /**
94     * Set opening text.
95     *
96     * @param string $value
97     */
98    public function setOpeningText($value): void
99    {
100        $this->openingText = $value;
101    }
102
103    /**
104     * Set closing text.
105     *
106     * @param string $value
107     */
108    public function setClosingText($value): void
109    {
110        $this->closingText = $value;
111    }
112
113    /**
114     * Write opening.
115     *
116     * @return string
117     */
118    protected function writeOpening()
119    {
120        $content = '';
121        if (!$this->withoutP) {
122            $style = $this->getParagraphStyle();
123            $content .= "<p{$style}>";
124        }
125
126        //open track change tag
127        $content .= $this->writeTrackChangeOpening();
128
129        return $content;
130    }
131
132    /**
133     * Write ending.
134     *
135     * @return string
136     */
137    protected function writeClosing()
138    {
139        $content = '';
140
141        //close track change tag
142        $content .= $this->writeTrackChangeClosing();
143
144        if (!$this->withoutP) {
145            $content .= $this->parentWriter->escapeHTML($this->closingText);
146            $content .= '</p>' . PHP_EOL;
147        }
148
149        return $content;
150    }
151
152    /**
153     * writes the track change opening tag.
154     *
155     * @return string the HTML, an empty string if no track change information
156     */
157    private function writeTrackChangeOpening()
158    {
159        $changed = $this->element->getTrackChange();
160        if ($changed == null) {
161            return '';
162        }
163
164        $content = '';
165        if (($changed->getChangeType() == TrackChange::INSERTED)) {
166            $content .= '<ins data-phpword-prop=\'';
167        } elseif ($changed->getChangeType() == TrackChange::DELETED) {
168            $content .= '<del data-phpword-prop=\'';
169        }
170
171        $changedProp = ['changed' => ['author' => $changed->getAuthor(), 'id' => $this->element->getElementId()]];
172        if ($changed->getDate() != null) {
173            $changedProp['changed']['date'] = $changed->getDate()->format('Y-m-d\TH:i:s\Z');
174        }
175        $content .= json_encode($changedProp);
176        $content .= '\' ';
177        $content .= 'title="' . $changed->getAuthor();
178        if ($changed->getDate() != null) {
179            $dateUser = $changed->getDate()->format('Y-m-d H:i:s');
180            $content .= ' - ' . $dateUser;
181        }
182        $content .= '">';
183
184        return $content;
185    }
186
187    /**
188     * writes the track change closing tag.
189     *
190     * @return string the HTML, an empty string if no track change information
191     */
192    private function writeTrackChangeClosing()
193    {
194        $changed = $this->element->getTrackChange();
195        if ($changed == null) {
196            return '';
197        }
198
199        $content = '';
200        if (($changed->getChangeType() == TrackChange::INSERTED)) {
201            $content .= '</ins>';
202        } elseif ($changed->getChangeType() == TrackChange::DELETED) {
203            $content .= '</del>';
204        }
205
206        return $content;
207    }
208
209    /**
210     * Write paragraph style.
211     *
212     * @return string
213     */
214    private function getParagraphStyle()
215    {
216        /** @var \PhpOffice\PhpWord\Element\Text $element Type hint */
217        $element = $this->element;
218        $style = '';
219        if (!method_exists($element, 'getParagraphStyle')) {
220            return $style;
221        }
222
223        $paragraphStyle = $element->getParagraphStyle();
224        $pStyleIsObject = ($paragraphStyle instanceof Paragraph);
225        if ($pStyleIsObject) {
226            $styleWriter = new ParagraphStyleWriter($paragraphStyle);
227            $styleWriter->setParentWriter($this->parentWriter);
228            $style = $styleWriter->write();
229        } elseif (is_string($paragraphStyle)) {
230            $style = $paragraphStyle;
231        }
232        if ($style) {
233            $attribute = $pStyleIsObject ? 'style' : 'class';
234            $style = " {$attribute}=\"{$style}\"";
235        }
236
237        return $style;
238    }
239
240    /**
241     * Get font style.
242     */
243    private function processFontStyle(): void
244    {
245        /** @var \PhpOffice\PhpWord\Element\Text $element Type hint */
246        $element = $this->element;
247
248        $attributeStyle = $attributeLang = '';
249        $lang = null;
250
251        $fontStyle = $element->getFontStyle();
252        if ($fontStyle instanceof Font) {
253            // Attribute style
254            $styleWriter = new FontStyleWriter($fontStyle);
255            $fontCSS = $styleWriter->write();
256            if ($fontCSS) {
257                $attributeStyle = ' style="' . $fontCSS . '"';
258            }
259            // Attribute Lang
260            $lang = $fontStyle->getLang();
261        } elseif (!empty($fontStyle)) {
262            // Attribute class
263            $attributeStyle = ' class="' . $fontStyle . '"';
264            // Attribute Lang
265            /** @var Font $cssClassStyle */
266            $cssClassStyle = Style::getStyle($fontStyle);
267            if ($cssClassStyle !== null && method_exists($cssClassStyle, 'getLang')) {
268                $lang = $cssClassStyle->getLang();
269            }
270        }
271
272        if ($lang) {
273            $attributeLang = $lang->getLatin();
274            if (!$attributeLang) {
275                $attributeLang = $lang->getEastAsia();
276            }
277            if (!$attributeLang) {
278                $attributeLang = $lang->getBidirectional();
279            }
280            if ($attributeLang) {
281                $attributeLang = " lang='$attributeLang'";
282            }
283        }
284
285        if ($attributeStyle || $attributeLang) {
286            $this->openingTags = "<span$attributeLang$attributeStyle>";
287            $this->closingTags = '</span>';
288        }
289    }
290}