Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
82 / 82 |
|
100.00% |
3 / 3 |
CRAP | |
100.00% |
1 / 1 |
Table | |
100.00% |
82 / 82 |
|
100.00% |
3 / 3 |
33 | |
100.00% |
1 / 1 |
write | |
100.00% |
48 / 48 |
|
100.00% |
1 / 1 |
20 | |||
getTableStyle | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
4 | |||
calculateCellRowSpan | |
100.00% |
25 / 25 |
|
100.00% |
1 / 1 |
9 |
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 | |
18 | namespace PhpOffice\PhpWord\Writer\HTML\Element; |
19 | |
20 | use PhpOffice\PhpWord\Writer\HTML\Style\Table as TableStyleWriter; |
21 | |
22 | /** |
23 | * Table element HTML writer. |
24 | * |
25 | * @since 0.10.0 |
26 | */ |
27 | class Table extends AbstractElement |
28 | { |
29 | /** |
30 | * Write table. |
31 | * |
32 | * @return string |
33 | */ |
34 | public function write() |
35 | { |
36 | if (!$this->element instanceof \PhpOffice\PhpWord\Element\Table) { |
37 | return ''; |
38 | } |
39 | |
40 | $content = ''; |
41 | $rows = $this->element->getRows(); |
42 | $rowCount = count($rows); |
43 | if ($rowCount > 0) { |
44 | $content .= '<table' . $this->getTableStyle($this->element->getStyle()) . '>' . PHP_EOL; |
45 | |
46 | for ($i = 0; $i < $rowCount; ++$i) { |
47 | /** @var \PhpOffice\PhpWord\Element\Row $row Type hint */ |
48 | $rowStyle = $rows[$i]->getStyle(); |
49 | // $height = $row->getHeight(); |
50 | $tblHeader = $rowStyle->isTblHeader(); |
51 | $content .= '<tr>' . PHP_EOL; |
52 | $rowCells = $rows[$i]->getCells(); |
53 | $rowCellCount = count($rowCells); |
54 | for ($j = 0; $j < $rowCellCount; ++$j) { |
55 | $cellStyle = $rowCells[$j]->getStyle(); |
56 | $cellStyleCss = $this->getTableStyle($cellStyle); |
57 | $cellBgColor = $cellStyle->getBgColor(); |
58 | $cellFgColor = null; |
59 | if ($cellBgColor && $cellBgColor !== 'auto') { |
60 | $red = hexdec(substr($cellBgColor, 0, 2)); |
61 | $green = hexdec(substr($cellBgColor, 2, 2)); |
62 | $blue = hexdec(substr($cellBgColor, 4, 2)); |
63 | $cellFgColor = (($red * 0.299 + $green * 0.587 + $blue * 0.114) > 186) ? null : 'ffffff'; |
64 | } |
65 | $cellColSpan = $cellStyle->getGridSpan(); |
66 | $cellRowSpan = 1; |
67 | $cellVMerge = $cellStyle->getVMerge(); |
68 | // If this is the first cell of the vertical merge, find out how many rows it spans |
69 | if ($cellVMerge === 'restart') { |
70 | $cellRowSpan = $this->calculateCellRowSpan($rows, $i, $j); |
71 | } |
72 | // Ignore cells that are merged vertically with previous rows |
73 | if ($cellVMerge !== 'continue') { |
74 | $cellTag = $tblHeader ? 'th' : 'td'; |
75 | $cellColSpanAttr = (is_numeric($cellColSpan) && ($cellColSpan > 1) ? " colspan=\"{$cellColSpan}\"" : ''); |
76 | $cellRowSpanAttr = ($cellRowSpan > 1 ? " rowspan=\"{$cellRowSpan}\"" : ''); |
77 | $cellBgColorAttr = (empty($cellBgColor) ? '' : " bgcolor=\"#{$cellBgColor}\""); |
78 | $cellFgColorAttr = (empty($cellFgColor) ? '' : " color=\"#{$cellFgColor}\""); |
79 | $content .= "<{$cellTag}{$cellStyleCss}{$cellColSpanAttr}{$cellRowSpanAttr}{$cellBgColorAttr}{$cellFgColorAttr}>" . PHP_EOL; |
80 | $writer = new Container($this->parentWriter, $rowCells[$j]); |
81 | $content .= $writer->write(); |
82 | if ($cellRowSpan > 1) { |
83 | // There shouldn't be any content in the subsequent merged cells, but lets check anyway |
84 | for ($k = $i + 1; $k < $rowCount; ++$k) { |
85 | $kRowCells = $rows[$k]->getCells(); |
86 | if (isset($kRowCells[$j]) && $kRowCells[$j]->getStyle()->getVMerge() === 'continue') { |
87 | $writer = new Container($this->parentWriter, $kRowCells[$j]); |
88 | $content .= $writer->write(); |
89 | } else { |
90 | break; |
91 | } |
92 | } |
93 | } |
94 | $content .= "</{$cellTag}>" . PHP_EOL; |
95 | } |
96 | } |
97 | $content .= '</tr>' . PHP_EOL; |
98 | } |
99 | $content .= '</table>' . PHP_EOL; |
100 | } |
101 | |
102 | return $content; |
103 | } |
104 | |
105 | /** |
106 | * Translates Table style in CSS equivalent. |
107 | * |
108 | * @param null|\PhpOffice\PhpWord\Style\Cell|\PhpOffice\PhpWord\Style\Table|string $tableStyle |
109 | */ |
110 | private function getTableStyle($tableStyle = null): string |
111 | { |
112 | if ($tableStyle == null) { |
113 | return ''; |
114 | } |
115 | if (is_string($tableStyle)) { |
116 | return ' class="' . $tableStyle . '"'; |
117 | } |
118 | |
119 | $styleWriter = new TableStyleWriter($tableStyle); |
120 | $style = $styleWriter->write(); |
121 | if ($style === '') { |
122 | return ''; |
123 | } |
124 | |
125 | return ' style="' . $style . '"'; |
126 | } |
127 | |
128 | /** |
129 | * Calculates cell rowspan. |
130 | * |
131 | * @param \PhpOffice\PhpWord\Element\Row[] $rows |
132 | */ |
133 | private function calculateCellRowSpan(array $rows, int $rowIndex, int $colIndex): int |
134 | { |
135 | $currentRow = $rows[$rowIndex]; |
136 | $currentRowCells = $currentRow->getCells(); |
137 | $shiftedColIndex = 0; |
138 | |
139 | foreach ($currentRowCells as $cell) { |
140 | if ($cell === $currentRowCells[$colIndex]) { |
141 | break; |
142 | } |
143 | |
144 | $colSpan = 1; |
145 | |
146 | if ($cell->getStyle()->getGridSpan() !== null) { |
147 | $colSpan = $cell->getStyle()->getGridSpan(); |
148 | } |
149 | |
150 | $shiftedColIndex += $colSpan; |
151 | } |
152 | |
153 | $rowCount = count($rows); |
154 | $rowSpan = 1; |
155 | |
156 | for ($i = $rowIndex + 1; $i < $rowCount; ++$i) { |
157 | $rowCells = $rows[$i]->getCells(); |
158 | $colIndex = 0; |
159 | |
160 | foreach ($rowCells as $cell) { |
161 | if ($colIndex === $shiftedColIndex) { |
162 | if ($cell->getStyle()->getVMerge() === 'continue') { |
163 | ++$rowSpan; |
164 | } |
165 | |
166 | break; |
167 | } |
168 | |
169 | $colSpan = 1; |
170 | |
171 | if ($cell->getStyle()->getGridSpan() !== null) { |
172 | $colSpan = $cell->getStyle()->getGridSpan(); |
173 | } |
174 | |
175 | $colIndex += $colSpan; |
176 | } |
177 | } |
178 | |
179 | return $rowSpan; |
180 | } |
181 | } |