Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
147 / 147 |
|
100.00% |
5 / 5 |
CRAP | |
100.00% |
1 / 1 |
Styles | |
100.00% |
147 / 147 |
|
100.00% |
5 / 5 |
26 | |
100.00% |
1 / 1 |
write | |
100.00% |
17 / 17 |
|
100.00% |
1 / 1 |
5 | |||
writeDefaultStyles | |
100.00% |
67 / 67 |
|
100.00% |
1 / 1 |
9 | |||
writeFontStyle | |
100.00% |
36 / 36 |
|
100.00% |
1 / 1 |
10 | |||
writeParagraphStyle | |
100.00% |
14 / 14 |
|
100.00% |
1 / 1 |
1 | |||
writeTableStyle | |
100.00% |
13 / 13 |
|
100.00% |
1 / 1 |
1 |
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\Part; |
20 | |
21 | use PhpOffice\PhpWord\Shared\XMLWriter; |
22 | use PhpOffice\PhpWord\Style; |
23 | use PhpOffice\PhpWord\Style\Font as FontStyle; |
24 | use PhpOffice\PhpWord\Style\Paragraph as ParagraphStyle; |
25 | use PhpOffice\PhpWord\Style\Table as TableStyle; |
26 | use PhpOffice\PhpWord\Writer\Word2007\Style\Font as FontStyleWriter; |
27 | use PhpOffice\PhpWord\Writer\Word2007\Style\Paragraph as ParagraphStyleWriter; |
28 | use PhpOffice\PhpWord\Writer\Word2007\Style\Table as TableStyleWriter; |
29 | |
30 | /** |
31 | * Word2007 styles part writer: word/styles.xml. |
32 | * |
33 | * @todo Do something with the numbering style introduced in 0.10.0 |
34 | * |
35 | * @SuppressWarnings(PHPMD.UnusedPrivateMethod) For writeFontStyle, writeParagraphStyle, and writeTableStyle |
36 | */ |
37 | class Styles extends AbstractPart |
38 | { |
39 | /** |
40 | * Write part. |
41 | * |
42 | * @return string |
43 | */ |
44 | public function write() |
45 | { |
46 | $xmlWriter = $this->getXmlWriter(); |
47 | |
48 | $xmlWriter->startDocument('1.0', 'UTF-8', 'yes'); |
49 | $xmlWriter->startElement('w:styles'); |
50 | $xmlWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); |
51 | $xmlWriter->writeAttribute('xmlns:w', 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'); |
52 | |
53 | // Write default styles |
54 | $styles = Style::getStyles(); |
55 | $this->writeDefaultStyles($xmlWriter, $styles); |
56 | |
57 | // Write styles |
58 | if (count($styles) > 0) { |
59 | foreach ($styles as $styleName => $style) { |
60 | if ($styleName == 'Normal') { |
61 | continue; |
62 | } |
63 | |
64 | // Get style class and execute if the private method exists |
65 | $styleClass = substr(get_class($style), strrpos(get_class($style), '\\') + 1); |
66 | $method = "write{$styleClass}Style"; |
67 | if (method_exists($this, $method)) { |
68 | $this->$method($xmlWriter, $styleName, $style); |
69 | } |
70 | } |
71 | } |
72 | |
73 | $xmlWriter->endElement(); // w:styles |
74 | |
75 | return $xmlWriter->getData(); |
76 | } |
77 | |
78 | /** |
79 | * Write default font and other default styles. |
80 | * |
81 | * @param Style\AbstractStyle[] $styles |
82 | */ |
83 | private function writeDefaultStyles(XMLWriter $xmlWriter, $styles): void |
84 | { |
85 | $phpWord = $this->getParentWriter()->getPhpWord(); |
86 | $fontName = $phpWord->getDefaultFontName(); |
87 | $asianFontName = $phpWord->getDefaultAsianFontName(); |
88 | $fontSize = $phpWord->getDefaultFontSize(); |
89 | $fontColor = $phpWord->getDefaultFontColor(); |
90 | $language = $phpWord->getSettings()->getThemeFontLang(); |
91 | $latinLanguage = ($language == null || $language->getLatin() === null) ? 'en-US' : $language->getLatin(); |
92 | |
93 | // Default font |
94 | $xmlWriter->startElement('w:docDefaults'); |
95 | $xmlWriter->startElement('w:rPrDefault'); |
96 | $xmlWriter->startElement('w:rPr'); |
97 | $xmlWriter->startElement('w:rFonts'); |
98 | $xmlWriter->writeAttribute('w:ascii', $fontName); |
99 | $xmlWriter->writeAttribute('w:hAnsi', $fontName); |
100 | $xmlWriter->writeAttribute('w:eastAsia', $asianFontName); |
101 | $xmlWriter->writeAttribute('w:cs', $fontName); |
102 | $xmlWriter->endElement(); // w:rFonts |
103 | $xmlWriter->startElement('w:color'); |
104 | $xmlWriter->writeAttribute('w:val', $fontColor); |
105 | $xmlWriter->endElement(); |
106 | $xmlWriter->startElement('w:sz'); |
107 | $xmlWriter->writeAttribute('w:val', $fontSize * 2); |
108 | $xmlWriter->endElement(); // w:sz |
109 | $xmlWriter->startElement('w:szCs'); |
110 | $xmlWriter->writeAttribute('w:val', $fontSize * 2); |
111 | $xmlWriter->endElement(); // w:szCs |
112 | $xmlWriter->startElement('w:lang'); |
113 | $xmlWriter->writeAttribute('w:val', $latinLanguage); |
114 | if ($language != null) { |
115 | $xmlWriter->writeAttributeIf($language->getEastAsia() !== null, 'w:eastAsia', $language->getEastAsia()); |
116 | $xmlWriter->writeAttributeIf($language->getBidirectional() !== null, 'w:bidi', $language->getBidirectional()); |
117 | } |
118 | $xmlWriter->endElement(); // w:lang |
119 | $xmlWriter->endElement(); // w:rPr |
120 | $xmlWriter->endElement(); // w:rPrDefault |
121 | $xmlWriter->endElement(); // w:docDefaults |
122 | |
123 | // Normal style |
124 | $xmlWriter->startElement('w:style'); |
125 | $xmlWriter->writeAttribute('w:type', 'paragraph'); |
126 | $xmlWriter->writeAttribute('w:default', '1'); |
127 | $xmlWriter->writeAttribute('w:styleId', 'Normal'); |
128 | $xmlWriter->startElement('w:name'); |
129 | $xmlWriter->writeAttribute('w:val', 'Normal'); |
130 | $xmlWriter->endElement(); // w:name |
131 | if (isset($styles['Normal'])) { |
132 | $normalStyle = $styles['Normal']; |
133 | // w:pPr |
134 | if ($normalStyle instanceof FontStyle && $normalStyle->getParagraph() != null) { |
135 | $styleWriter = new ParagraphStyleWriter($xmlWriter, $normalStyle->getParagraph()); |
136 | $styleWriter->write(); |
137 | } elseif ($normalStyle instanceof ParagraphStyle) { |
138 | $styleWriter = new ParagraphStyleWriter($xmlWriter, $normalStyle); |
139 | $styleWriter->write(); |
140 | } |
141 | |
142 | // w:rPr |
143 | $styleWriter = new FontStyleWriter($xmlWriter, $normalStyle); |
144 | $styleWriter->write(); |
145 | } |
146 | $xmlWriter->endElement(); // w:style |
147 | |
148 | // FootnoteReference style |
149 | if (!isset($styles['FootnoteReference'])) { |
150 | $xmlWriter->startElement('w:style'); |
151 | $xmlWriter->writeAttribute('w:type', 'character'); |
152 | $xmlWriter->writeAttribute('w:styleId', 'FootnoteReference'); |
153 | $xmlWriter->startElement('w:name'); |
154 | $xmlWriter->writeAttribute('w:val', 'Footnote Reference'); |
155 | $xmlWriter->endElement(); // w:name |
156 | $xmlWriter->writeElement('w:semiHidden'); |
157 | $xmlWriter->writeElement('w:unhideWhenUsed'); |
158 | $xmlWriter->startElement('w:rPr'); |
159 | $xmlWriter->startElement('w:vertAlign'); |
160 | $xmlWriter->writeAttribute('w:val', 'superscript'); |
161 | $xmlWriter->endElement(); // w:vertAlign |
162 | $xmlWriter->endElement(); // w:rPr |
163 | $xmlWriter->endElement(); // w:style |
164 | } |
165 | } |
166 | |
167 | /** |
168 | * Write font style. |
169 | * |
170 | * @param string $styleName |
171 | */ |
172 | private function writeFontStyle(XMLWriter $xmlWriter, $styleName, FontStyle $style): void |
173 | { |
174 | $paragraphStyle = $style->getParagraph(); |
175 | $styleType = $style->getStyleType(); |
176 | $type = ($styleType == 'title') ? 'paragraph' : 'character'; |
177 | if (null !== $paragraphStyle) { |
178 | $type = 'paragraph'; |
179 | } |
180 | |
181 | $xmlWriter->startElement('w:style'); |
182 | $xmlWriter->writeAttribute('w:type', $type); |
183 | |
184 | // Heading style |
185 | if ($styleType == 'title') { |
186 | $arrStyle = explode('_', $styleName); |
187 | if (count($arrStyle) > 1) { |
188 | $styleId = 'Heading' . $arrStyle[1]; |
189 | $styleName = 'heading ' . $arrStyle[1]; |
190 | $styleLink = 'Heading' . $arrStyle[1] . 'Char'; |
191 | } else { |
192 | $styleId = $styleName; |
193 | $styleName = strtolower($styleName); |
194 | $styleLink = $styleName . 'Char'; |
195 | } |
196 | $xmlWriter->writeAttribute('w:styleId', $styleId); |
197 | |
198 | $xmlWriter->startElement('w:link'); |
199 | $xmlWriter->writeAttribute('w:val', $styleLink); |
200 | $xmlWriter->endElement(); |
201 | } elseif (null !== $paragraphStyle) { |
202 | // if type is 'paragraph' it should have a styleId |
203 | $xmlWriter->writeAttribute('w:styleId', $styleName); |
204 | } |
205 | |
206 | // Style name |
207 | $xmlWriter->startElement('w:name'); |
208 | $xmlWriter->writeAttribute('w:val', $styleName); |
209 | $xmlWriter->endElement(); |
210 | |
211 | // Parent style |
212 | if (null !== $paragraphStyle) { |
213 | if ($paragraphStyle->getStyleName() != null) { |
214 | $xmlWriter->writeElementBlock('w:basedOn', 'w:val', $paragraphStyle->getStyleName()); |
215 | } elseif ($paragraphStyle->getBasedOn() != null) { |
216 | $xmlWriter->writeElementBlock('w:basedOn', 'w:val', $paragraphStyle->getBasedOn()); |
217 | } |
218 | } |
219 | |
220 | // w:pPr |
221 | if (null !== $paragraphStyle) { |
222 | $styleWriter = new ParagraphStyleWriter($xmlWriter, $paragraphStyle); |
223 | $styleWriter->write(); |
224 | } |
225 | |
226 | // w:rPr |
227 | $styleWriter = new FontStyleWriter($xmlWriter, $style); |
228 | $styleWriter->write(); |
229 | |
230 | $xmlWriter->endElement(); |
231 | } |
232 | |
233 | /** |
234 | * Write paragraph style. |
235 | * |
236 | * @param string $styleName |
237 | */ |
238 | private function writeParagraphStyle(XMLWriter $xmlWriter, $styleName, ParagraphStyle $style): void |
239 | { |
240 | $xmlWriter->startElement('w:style'); |
241 | $xmlWriter->writeAttribute('w:type', 'paragraph'); |
242 | $xmlWriter->writeAttribute('w:customStyle', '1'); |
243 | $xmlWriter->writeAttribute('w:styleId', $styleName); |
244 | $xmlWriter->startElement('w:name'); |
245 | $xmlWriter->writeAttribute('w:val', $styleName); |
246 | $xmlWriter->endElement(); |
247 | |
248 | // Parent style |
249 | $basedOn = $style->getBasedOn(); |
250 | $xmlWriter->writeElementIf(null !== $basedOn, 'w:basedOn', 'w:val', $basedOn); |
251 | |
252 | // Next paragraph style |
253 | $next = $style->getNext(); |
254 | $xmlWriter->writeElementIf(null !== $next, 'w:next', 'w:val', $next); |
255 | |
256 | // w:pPr |
257 | $styleWriter = new ParagraphStyleWriter($xmlWriter, $style); |
258 | $styleWriter->write(); |
259 | |
260 | $xmlWriter->endElement(); |
261 | } |
262 | |
263 | /** |
264 | * Write table style. |
265 | * |
266 | * @param string $styleName |
267 | */ |
268 | private function writeTableStyle(XMLWriter $xmlWriter, $styleName, TableStyle $style): void |
269 | { |
270 | $xmlWriter->startElement('w:style'); |
271 | $xmlWriter->writeAttribute('w:type', 'table'); |
272 | $xmlWriter->writeAttribute('w:customStyle', '1'); |
273 | $xmlWriter->writeAttribute('w:styleId', $styleName); |
274 | $xmlWriter->startElement('w:name'); |
275 | $xmlWriter->writeAttribute('w:val', $styleName); |
276 | $xmlWriter->endElement(); |
277 | $xmlWriter->startElement('w:uiPriority'); |
278 | $xmlWriter->writeAttribute('w:val', '99'); |
279 | $xmlWriter->endElement(); |
280 | |
281 | $styleWriter = new TableStyleWriter($xmlWriter, $style); |
282 | $styleWriter->write(); |
283 | |
284 | $xmlWriter->endElement(); // w:style |
285 | } |
286 | } |