Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
99.12% |
112 / 113 |
|
66.67% |
2 / 3 |
CRAP | |
0.00% |
0 / 1 |
Head | |
99.12% |
112 / 113 |
|
66.67% |
2 / 3 |
22 | |
0.00% |
0 / 1 |
write | |
100.00% |
29 / 29 |
|
100.00% |
1 / 1 |
5 | |||
writeStyles | |
100.00% |
78 / 78 |
|
100.00% |
1 / 1 |
14 | |||
getFontFamily | |
83.33% |
5 / 6 |
|
0.00% |
0 / 1 |
3.04 |
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\HTML\Part; |
20 | |
21 | use PhpOffice\PhpWord\Settings; |
22 | use PhpOffice\PhpWord\Shared\Converter; |
23 | use PhpOffice\PhpWord\Style; |
24 | use PhpOffice\PhpWord\Style\Font; |
25 | use PhpOffice\PhpWord\Style\Paragraph; |
26 | use PhpOffice\PhpWord\Style\Table; |
27 | use PhpOffice\PhpWord\Writer\HTML\Style\Font as FontStyleWriter; |
28 | use PhpOffice\PhpWord\Writer\HTML\Style\Generic as GenericStyleWriter; |
29 | use PhpOffice\PhpWord\Writer\HTML\Style\Paragraph as ParagraphStyleWriter; |
30 | use PhpOffice\PhpWord\Writer\HTML\Style\Table as TableStyleWriter; |
31 | |
32 | /** |
33 | * HTML head part writer. |
34 | * |
35 | * @since 0.11.0 |
36 | */ |
37 | class Head extends AbstractPart |
38 | { |
39 | /** |
40 | * Write part. |
41 | * |
42 | * @return string |
43 | */ |
44 | public function write() |
45 | { |
46 | $docProps = $this->getParentWriter()->getPhpWord()->getDocInfo(); |
47 | $propertiesMapping = [ |
48 | 'creator' => 'author', |
49 | 'title' => '', |
50 | 'description' => '', |
51 | 'subject' => '', |
52 | 'keywords' => '', |
53 | 'category' => '', |
54 | 'company' => '', |
55 | 'manager' => '', |
56 | ]; |
57 | $title = $docProps->getTitle(); |
58 | $title = ($title != '') ? $title : 'PHPWord'; |
59 | |
60 | $content = ''; |
61 | |
62 | $content .= '<head>' . PHP_EOL; |
63 | $content .= '<meta charset="UTF-8" />' . PHP_EOL; |
64 | $content .= '<title>' . $title . '</title>' . PHP_EOL; |
65 | foreach ($propertiesMapping as $key => $value) { |
66 | $value = ($value == '') ? $key : $value; |
67 | $method = 'get' . $key; |
68 | if ($docProps->$method() != '') { |
69 | $content .= '<meta name="' . $value . '"' |
70 | . ' content="' |
71 | . $this->getParentWriter()->escapeHTML($docProps->$method()) |
72 | . '"' |
73 | . ' />' . PHP_EOL; |
74 | } |
75 | } |
76 | $content .= $this->writeStyles(); |
77 | $content .= '</head>' . PHP_EOL; |
78 | |
79 | return $content; |
80 | } |
81 | |
82 | /** |
83 | * Get styles. |
84 | */ |
85 | private function writeStyles(): string |
86 | { |
87 | $css = '<style>' . PHP_EOL; |
88 | $defaultFontColor = Settings::getDefaultFontColor(); |
89 | // Default styles |
90 | $astarray = [ |
91 | 'font-family' => $this->getFontFamily(Settings::getDefaultFontName(), $this->getParentWriter()->getDefaultGenericFont()), |
92 | 'font-size' => Settings::getDefaultFontSize() . 'pt', |
93 | 'color' => "#{$defaultFontColor}", |
94 | ]; |
95 | // Mpdf sometimes needs separate tag for body; doesn't harm others. |
96 | $bodyarray = $astarray; |
97 | |
98 | $defaultWhiteSpace = $this->getParentWriter()->getDefaultWhiteSpace(); |
99 | if ($defaultWhiteSpace) { |
100 | $astarray['white-space'] = $defaultWhiteSpace; |
101 | } |
102 | |
103 | foreach ([ |
104 | 'body' => $bodyarray, |
105 | '*' => $astarray, |
106 | 'a.NoteRef' => [ |
107 | 'text-decoration' => 'none', |
108 | ], |
109 | 'hr' => [ |
110 | 'height' => '1px', |
111 | 'padding' => '0', |
112 | 'margin' => '1em 0', |
113 | 'border' => '0', |
114 | 'border-top' => '1px solid #CCC', |
115 | ], |
116 | 'table' => [ |
117 | 'border' => '1px solid black', |
118 | 'border-spacing' => '0px', |
119 | 'width ' => '100%', |
120 | ], |
121 | 'td' => [ |
122 | 'border' => '1px solid black', |
123 | ], |
124 | ] as $selector => $style) { |
125 | $styleWriter = new GenericStyleWriter($style); |
126 | $css .= $selector . ' {' . $styleWriter->write() . '}' . PHP_EOL; |
127 | } |
128 | |
129 | // Custom styles |
130 | $customStyles = Style::getStyles(); |
131 | if (is_array($customStyles)) { |
132 | foreach ($customStyles as $name => $style) { |
133 | $styleParagraph = null; |
134 | if ($style instanceof Font) { |
135 | $styleWriter = new FontStyleWriter($style); |
136 | if ($style->getStyleType() == 'title') { |
137 | $name = str_replace('Heading_', 'h', $name); |
138 | $styleParagraph = $style->getParagraph(); |
139 | $style = $styleParagraph; |
140 | } else { |
141 | $name = '.' . $name; |
142 | } |
143 | $css .= "{$name} {" . $styleWriter->write() . '}' . PHP_EOL; |
144 | } |
145 | if ($style instanceof Paragraph) { |
146 | $styleWriter = new ParagraphStyleWriter($style); |
147 | $styleWriter->setParentWriter($this->getParentWriter()); |
148 | if (!$styleParagraph) { |
149 | $name = '.' . $name; |
150 | } |
151 | if ($name === '.Normal') { |
152 | $name = "p, $name"; |
153 | } |
154 | $css .= "{$name} {" . $styleWriter->write() . '}' . PHP_EOL; |
155 | } |
156 | if ($style instanceof Table) { |
157 | $styleWriter = new TableStyleWriter($style); |
158 | $css .= ".{$name} {" . $styleWriter->write() . '}' . PHP_EOL; |
159 | } |
160 | } |
161 | } |
162 | |
163 | $css .= 'body > div + div {page-break-before: always;}' . PHP_EOL; |
164 | $css .= 'div > *:first-child {page-break-before: auto;}' . PHP_EOL; |
165 | |
166 | $sectionNum = 0; |
167 | foreach ($this->getParentWriter()->getPhpWord()->getSections() as $section) { |
168 | ++$sectionNum; |
169 | |
170 | $css .= "@page page$sectionNum {"; |
171 | |
172 | $paperSize = $section->getStyle()->getPaperSize(); |
173 | $orientation = $section->getStyle()->getOrientation(); |
174 | if ($this->getParentWriter()->isPdf()) { |
175 | if ($orientation === 'landscape') { |
176 | $paperSize .= '-L'; |
177 | } |
178 | $css .= "sheet-size: $paperSize; "; |
179 | } else { |
180 | $css .= "size: $paperSize $orientation; "; |
181 | } |
182 | |
183 | $css .= 'margin-right: ' . (string) ($section->getStyle()->getMarginRight() / Converter::INCH_TO_TWIP) . 'in; '; |
184 | $css .= 'margin-left: ' . (string) ($section->getStyle()->getMarginLeft() / Converter::INCH_TO_TWIP) . 'in; '; |
185 | $css .= 'margin-top: ' . (string) ($section->getStyle()->getMarginTop() / Converter::INCH_TO_TWIP) . 'in; '; |
186 | $css .= 'margin-bottom: ' . (string) ($section->getStyle()->getMarginBottom() / Converter::INCH_TO_TWIP) . 'in; '; |
187 | $css .= '}' . PHP_EOL; |
188 | } |
189 | |
190 | $css .= '</style>' . PHP_EOL; |
191 | |
192 | return $css; |
193 | } |
194 | |
195 | /** |
196 | * Set font and alternates for css font-family. |
197 | */ |
198 | private function getFontFamily(string $font, string $genericFont): string |
199 | { |
200 | if (empty($font)) { |
201 | return ''; |
202 | } |
203 | $fontfamily = "'" . htmlspecialchars($font, ENT_QUOTES, 'UTF-8') . "'"; |
204 | if (!empty($genericFont)) { |
205 | $fontfamily .= ", $genericFont"; |
206 | } |
207 | |
208 | return $fontfamily; |
209 | } |
210 | } |