Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
88.38% |
175 / 198 |
|
66.67% |
4 / 6 |
CRAP | |
0.00% |
0 / 1 |
Field | |
88.38% |
175 / 198 |
|
66.67% |
4 / 6 |
50.46 | |
0.00% |
0 / 1 |
write | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
3 | |||
writeDefault | |
100.00% |
54 / 54 |
|
100.00% |
1 / 1 |
7 | |||
writeMacrobutton | |
100.00% |
26 / 26 |
|
100.00% |
1 / 1 |
4 | |||
buildPropertiesAndOptions | |
100.00% |
42 / 42 |
|
100.00% |
1 / 1 |
16 | |||
writeRef | |
73.08% |
38 / 52 |
|
0.00% |
0 / 1 |
7.96 | |||
convertRefOption | |
47.06% |
8 / 17 |
|
0.00% |
0 / 1 |
24.84 |
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 | |
19 | namespace PhpOffice\PhpWord\Writer\Word2007\Element; |
20 | |
21 | use PhpOffice\PhpWord\Element\Field as ElementField; |
22 | use PhpOffice\PhpWord\Element\TextRun; |
23 | |
24 | /** |
25 | * Field element writer. |
26 | * |
27 | * @since 0.11.0 |
28 | */ |
29 | class Field extends Text |
30 | { |
31 | /** |
32 | * Write field element. |
33 | */ |
34 | public function write(): void |
35 | { |
36 | $element = $this->getElement(); |
37 | if (!$element instanceof ElementField) { |
38 | return; |
39 | } |
40 | |
41 | $methodName = 'write' . ucfirst(strtolower($element->getType())); |
42 | if (method_exists($this, $methodName)) { |
43 | $this->$methodName($element); |
44 | } else { |
45 | $this->writeDefault($element); |
46 | } |
47 | } |
48 | |
49 | private function writeDefault(ElementField $element): void |
50 | { |
51 | $xmlWriter = $this->getXmlWriter(); |
52 | $this->startElementP(); |
53 | |
54 | $xmlWriter->startElement('w:r'); |
55 | $xmlWriter->startElement('w:fldChar'); |
56 | $xmlWriter->writeAttribute('w:fldCharType', 'begin'); |
57 | $xmlWriter->endElement(); // w:fldChar |
58 | $xmlWriter->endElement(); // w:r |
59 | |
60 | $instruction = ' ' . $element->getType() . ' '; |
61 | if ($element->getText() != null) { |
62 | if (is_string($element->getText())) { |
63 | $instruction .= '"' . $element->getText() . '" '; |
64 | $instruction .= $this->buildPropertiesAndOptions($element); |
65 | } else { |
66 | $instruction .= '"'; |
67 | } |
68 | } else { |
69 | $instruction .= $this->buildPropertiesAndOptions($element); |
70 | } |
71 | $xmlWriter->startElement('w:r'); |
72 | $this->writeFontStyle(); |
73 | $xmlWriter->startElement('w:instrText'); |
74 | $xmlWriter->writeAttribute('xml:space', 'preserve'); |
75 | $xmlWriter->text($instruction); |
76 | $xmlWriter->endElement(); // w:instrText |
77 | $xmlWriter->endElement(); // w:r |
78 | |
79 | if ($element->getText() != null) { |
80 | if ($element->getText() instanceof TextRun) { |
81 | $containerWriter = new Container($xmlWriter, $element->getText(), true); |
82 | $containerWriter->write(); |
83 | |
84 | $xmlWriter->startElement('w:r'); |
85 | $xmlWriter->startElement('w:instrText'); |
86 | $xmlWriter->text('"' . $this->buildPropertiesAndOptions($element)); |
87 | $xmlWriter->endElement(); // w:instrText |
88 | $xmlWriter->endElement(); // w:r |
89 | |
90 | $xmlWriter->startElement('w:r'); |
91 | $xmlWriter->startElement('w:instrText'); |
92 | $xmlWriter->writeAttribute('xml:space', 'preserve'); |
93 | $xmlWriter->text(' '); |
94 | $xmlWriter->endElement(); // w:instrText |
95 | $xmlWriter->endElement(); // w:r |
96 | } |
97 | } |
98 | |
99 | $xmlWriter->startElement('w:r'); |
100 | $xmlWriter->startElement('w:fldChar'); |
101 | $xmlWriter->writeAttribute('w:fldCharType', 'separate'); |
102 | $xmlWriter->endElement(); // w:fldChar |
103 | $xmlWriter->endElement(); // w:r |
104 | |
105 | $xmlWriter->startElement('w:r'); |
106 | $xmlWriter->startElement('w:rPr'); |
107 | $xmlWriter->startElement('w:noProof'); |
108 | $xmlWriter->endElement(); // w:noProof |
109 | $xmlWriter->endElement(); // w:rPr |
110 | $xmlWriter->writeElement('w:t', $element->getText() != null && is_string($element->getText()) ? $element->getText() : '1'); |
111 | $xmlWriter->endElement(); // w:r |
112 | |
113 | $xmlWriter->startElement('w:r'); |
114 | $xmlWriter->startElement('w:fldChar'); |
115 | $xmlWriter->writeAttribute('w:fldCharType', 'end'); |
116 | $xmlWriter->endElement(); // w:fldChar |
117 | $xmlWriter->endElement(); // w:r |
118 | |
119 | $this->endElementP(); // w:p |
120 | } |
121 | |
122 | /** |
123 | * Writes a macrobutton field. |
124 | * |
125 | * //TODO A lot of code duplication with general method, should maybe be refactored |
126 | */ |
127 | protected function writeMacrobutton(ElementField $element): void |
128 | { |
129 | $xmlWriter = $this->getXmlWriter(); |
130 | $this->startElementP(); |
131 | |
132 | $xmlWriter->startElement('w:r'); |
133 | $xmlWriter->startElement('w:fldChar'); |
134 | $xmlWriter->writeAttribute('w:fldCharType', 'begin'); |
135 | $xmlWriter->endElement(); // w:fldChar |
136 | $xmlWriter->endElement(); // w:r |
137 | |
138 | $instruction = ' ' . $element->getType() . ' ' . $this->buildPropertiesAndOptions($element); |
139 | if (is_string($element->getText())) { |
140 | $instruction .= $element->getText() . ' '; |
141 | } |
142 | |
143 | $xmlWriter->startElement('w:r'); |
144 | $xmlWriter->startElement('w:instrText'); |
145 | $xmlWriter->writeAttribute('xml:space', 'preserve'); |
146 | $xmlWriter->text($instruction); |
147 | $xmlWriter->endElement(); // w:instrText |
148 | $xmlWriter->endElement(); // w:r |
149 | |
150 | if ($element->getText() != null) { |
151 | if ($element->getText() instanceof TextRun) { |
152 | $containerWriter = new Container($xmlWriter, $element->getText(), true); |
153 | $containerWriter->write(); |
154 | } |
155 | } |
156 | |
157 | $xmlWriter->startElement('w:r'); |
158 | $xmlWriter->startElement('w:fldChar'); |
159 | $xmlWriter->writeAttribute('w:fldCharType', 'end'); |
160 | $xmlWriter->endElement(); // w:fldChar |
161 | $xmlWriter->endElement(); // w:r |
162 | |
163 | $this->endElementP(); // w:p |
164 | } |
165 | |
166 | private function buildPropertiesAndOptions(ElementField $element) |
167 | { |
168 | $propertiesAndOptions = ''; |
169 | $properties = $element->getProperties(); |
170 | foreach ($properties as $propkey => $propval) { |
171 | switch ($propkey) { |
172 | case 'format': |
173 | $propertiesAndOptions .= '\\* ' . $propval . ' '; |
174 | |
175 | break; |
176 | case 'numformat': |
177 | $propertiesAndOptions .= '\\# ' . $propval . ' '; |
178 | |
179 | break; |
180 | case 'dateformat': |
181 | $propertiesAndOptions .= '\\@ "' . $propval . '" '; |
182 | |
183 | break; |
184 | case 'macroname': |
185 | $propertiesAndOptions .= $propval . ' '; |
186 | |
187 | break; |
188 | default: |
189 | $propertiesAndOptions .= '"' . $propval . '" '; |
190 | |
191 | break; |
192 | } |
193 | } |
194 | |
195 | $options = $element->getOptions(); |
196 | foreach ($options as $option) { |
197 | switch ($option) { |
198 | case 'PreserveFormat': |
199 | $propertiesAndOptions .= '\\* MERGEFORMAT '; |
200 | |
201 | break; |
202 | case 'LunarCalendar': |
203 | $propertiesAndOptions .= '\\h '; |
204 | |
205 | break; |
206 | case 'SakaEraCalendar': |
207 | $propertiesAndOptions .= '\\s '; |
208 | |
209 | break; |
210 | case 'LastUsedFormat': |
211 | $propertiesAndOptions .= '\\l '; |
212 | |
213 | break; |
214 | case 'Bold': |
215 | $propertiesAndOptions .= '\\b '; |
216 | |
217 | break; |
218 | case 'Italic': |
219 | $propertiesAndOptions .= '\\i '; |
220 | |
221 | break; |
222 | case 'Path': |
223 | $propertiesAndOptions .= '\\p '; |
224 | |
225 | break; |
226 | default: |
227 | $propertiesAndOptions .= $option . ' '; |
228 | } |
229 | } |
230 | |
231 | return $propertiesAndOptions; |
232 | } |
233 | |
234 | /** |
235 | * Writes a REF field. |
236 | */ |
237 | protected function writeRef(ElementField $element): void |
238 | { |
239 | $xmlWriter = $this->getXmlWriter(); |
240 | $this->startElementP(); |
241 | |
242 | $xmlWriter->startElement('w:r'); |
243 | $xmlWriter->startElement('w:fldChar'); |
244 | $xmlWriter->writeAttribute('w:fldCharType', 'begin'); |
245 | $xmlWriter->endElement(); // w:fldChar |
246 | $xmlWriter->endElement(); // w:r |
247 | |
248 | $instruction = ' ' . $element->getType() . ' '; |
249 | |
250 | foreach ($element->getProperties() as $property) { |
251 | $instruction .= $property . ' '; |
252 | } |
253 | foreach ($element->getOptions() as $optionKey => $optionValue) { |
254 | $instruction .= $this->convertRefOption($optionKey, $optionValue) . ' '; |
255 | } |
256 | |
257 | $xmlWriter->startElement('w:r'); |
258 | $this->writeFontStyle(); |
259 | $xmlWriter->startElement('w:instrText'); |
260 | $xmlWriter->writeAttribute('xml:space', 'preserve'); |
261 | $xmlWriter->text($instruction); |
262 | $xmlWriter->endElement(); // w:instrText |
263 | $xmlWriter->endElement(); // w:r |
264 | |
265 | if ($element->getText() != null) { |
266 | if ($element->getText() instanceof TextRun) { |
267 | $containerWriter = new Container($xmlWriter, $element->getText(), true); |
268 | $containerWriter->write(); |
269 | |
270 | $xmlWriter->startElement('w:r'); |
271 | $xmlWriter->startElement('w:instrText'); |
272 | $xmlWriter->text('"' . $this->buildPropertiesAndOptions($element)); |
273 | $xmlWriter->endElement(); // w:instrText |
274 | $xmlWriter->endElement(); // w:r |
275 | |
276 | $xmlWriter->startElement('w:r'); |
277 | $xmlWriter->startElement('w:instrText'); |
278 | $xmlWriter->writeAttribute('xml:space', 'preserve'); |
279 | $xmlWriter->text(' '); |
280 | $xmlWriter->endElement(); // w:instrText |
281 | $xmlWriter->endElement(); // w:r |
282 | } |
283 | } |
284 | |
285 | $xmlWriter->startElement('w:r'); |
286 | $xmlWriter->startElement('w:fldChar'); |
287 | $xmlWriter->writeAttribute('w:fldCharType', 'separate'); |
288 | $xmlWriter->endElement(); // w:fldChar |
289 | $xmlWriter->endElement(); // w:r |
290 | |
291 | $xmlWriter->startElement('w:r'); |
292 | $xmlWriter->startElement('w:rPr'); |
293 | $xmlWriter->startElement('w:noProof'); |
294 | $xmlWriter->endElement(); // w:noProof |
295 | $xmlWriter->endElement(); // w:rPr |
296 | $xmlWriter->writeElement('w:t', $element->getText() != null && is_string($element->getText()) ? $element->getText() : '1'); |
297 | $xmlWriter->endElement(); // w:r |
298 | |
299 | $xmlWriter->startElement('w:r'); |
300 | $xmlWriter->startElement('w:fldChar'); |
301 | $xmlWriter->writeAttribute('w:fldCharType', 'end'); |
302 | $xmlWriter->endElement(); // w:fldChar |
303 | $xmlWriter->endElement(); // w:r |
304 | |
305 | $this->endElementP(); // w:p |
306 | } |
307 | |
308 | private function convertRefOption(string $optionKey, string $optionValue): string |
309 | { |
310 | if ($optionKey === 'NumberSeperatorSequence') { |
311 | return '\\d ' . $optionValue; |
312 | } |
313 | |
314 | switch ($optionValue) { |
315 | case 'IncrementAndInsertText': |
316 | return '\\f'; |
317 | case 'CreateHyperLink': |
318 | return '\\h'; |
319 | case 'NoTrailingPeriod': |
320 | return '\\n'; |
321 | case 'IncludeAboveOrBelow': |
322 | return '\\p'; |
323 | case 'InsertParagraphNumberRelativeContext': |
324 | return '\\r'; |
325 | case 'SuppressNonDelimiterNonNumericalText': |
326 | return '\\t'; |
327 | case 'InsertParagraphNumberFullContext': |
328 | return '\\w'; |
329 | default: |
330 | return ''; |
331 | } |
332 | } |
333 | } |