Passed
Push — master ( 30369c...0dbe15 )
by
unknown
23:07 queued 15:34
created

Style::writeRowProperties()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 12
ccs 9
cts 9
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Writer\Ods\Cell;
4
5
use PhpOffice\PhpSpreadsheet\Helper\Dimension;
6
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
7
use PhpOffice\PhpSpreadsheet\Style\Alignment;
8
use PhpOffice\PhpSpreadsheet\Style\Border;
9
use PhpOffice\PhpSpreadsheet\Style\Borders;
10
use PhpOffice\PhpSpreadsheet\Style\Fill;
11
use PhpOffice\PhpSpreadsheet\Style\Font;
12
use PhpOffice\PhpSpreadsheet\Style\Style as CellStyle;
13
use PhpOffice\PhpSpreadsheet\Worksheet\ColumnDimension;
14
use PhpOffice\PhpSpreadsheet\Worksheet\RowDimension;
15
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
16
17
class Style
18
{
19
    public const CELL_STYLE_PREFIX = 'ce';
20
    public const COLUMN_STYLE_PREFIX = 'co';
21
    public const ROW_STYLE_PREFIX = 'ro';
22
    public const TABLE_STYLE_PREFIX = 'ta';
23
    public const INDENT_TO_INCHES = 0.1043; // undocumented, used trial and error
24
25
    private XMLWriter $writer;
26
27 43
    public function __construct(XMLWriter $writer)
28
    {
29 43
        $this->writer = $writer;
30
    }
31
32 43
    private function mapHorizontalAlignment(?string $horizontalAlignment): string
33
    {
34 43
        return match ($horizontalAlignment) {
35
            Alignment::HORIZONTAL_CENTER, Alignment::HORIZONTAL_CENTER_CONTINUOUS, Alignment::HORIZONTAL_DISTRIBUTED => 'center',
36
            Alignment::HORIZONTAL_RIGHT => 'end',
37
            Alignment::HORIZONTAL_FILL, Alignment::HORIZONTAL_JUSTIFY => 'justify',
38 43
            Alignment::HORIZONTAL_GENERAL, '', null => '',
39 43
            default => 'start',
40 43
        };
41
    }
42
43 43
    private function mapVerticalAlignment(string $verticalAlignment): string
44
    {
45 43
        return match ($verticalAlignment) {
46
            Alignment::VERTICAL_TOP => 'top',
47
            Alignment::VERTICAL_CENTER => 'middle',
48
            Alignment::VERTICAL_DISTRIBUTED, Alignment::VERTICAL_JUSTIFY => 'automatic',
49 43
            default => 'bottom',
50 43
        };
51
    }
52
53 43
    private function writeFillStyle(Fill $fill): void
54
    {
55 43
        switch ($fill->getFillType()) {
56
            case Fill::FILL_SOLID:
57 1
                $this->writer->writeAttribute('fo:background-color', sprintf(
58 1
                    '#%s',
59 1
                    strtolower($fill->getStartColor()->getRGB())
60 1
                ));
61
62 1
                break;
63
            case Fill::FILL_GRADIENT_LINEAR:
64
            case Fill::FILL_GRADIENT_PATH:
65
                /// TODO :: To be implemented
66
                break;
67
            case Fill::FILL_NONE:
68
            default:
69
        }
70
    }
71
72 43
    private function writeBordersStyle(Borders $borders): void
73
    {
74 43
        $this->writeBorderStyle('bottom', $borders->getBottom());
75 43
        $this->writeBorderStyle('left', $borders->getLeft());
76 43
        $this->writeBorderStyle('right', $borders->getRight());
77 43
        $this->writeBorderStyle('top', $borders->getTop());
78
    }
79
80 43
    private function writeBorderStyle(string $direction, Border $border): void
81
    {
82 43
        if ($border->getBorderStyle() === Border::BORDER_NONE) {
83 43
            return;
84
        }
85
86 1
        $this->writer->writeAttribute('fo:border-' . $direction, sprintf(
87 1
            '%s %s #%s',
88 1
            $this->mapBorderWidth($border),
89 1
            $this->mapBorderStyle($border),
90 1
            $border->getColor()->getRGB(),
91 1
        ));
92
    }
93
94 1
    private function mapBorderWidth(Border $border): string
95
    {
96 1
        switch ($border->getBorderStyle()) {
97
            case Border::BORDER_THIN:
98
            case Border::BORDER_DASHED:
99
            case Border::BORDER_DASHDOT:
100
            case Border::BORDER_DASHDOTDOT:
101
            case Border::BORDER_DOTTED:
102
            case Border::BORDER_HAIR:
103
                return '0.75pt';
104
            case Border::BORDER_MEDIUM:
105
            case Border::BORDER_MEDIUMDASHED:
106
            case Border::BORDER_MEDIUMDASHDOT:
107
            case Border::BORDER_MEDIUMDASHDOTDOT:
108
            case Border::BORDER_SLANTDASHDOT:
109
                return '1.75pt';
110
            case Border::BORDER_DOUBLE:
111
            case Border::BORDER_THICK:
112 1
                return '2.5pt';
113
        }
114
115
        return '1pt';
116
    }
117
118 1
    private function mapBorderStyle(Border $border): string
119
    {
120 1
        switch ($border->getBorderStyle()) {
121
            case Border::BORDER_DOTTED:
122
            case Border::BORDER_MEDIUMDASHDOTDOT:
123
                return Border::BORDER_DOTTED;
124
125
            case Border::BORDER_DASHED:
126
            case Border::BORDER_DASHDOT:
127
            case Border::BORDER_DASHDOTDOT:
128
            case Border::BORDER_MEDIUMDASHDOT:
129
            case Border::BORDER_MEDIUMDASHED:
130
            case Border::BORDER_SLANTDASHDOT:
131
                return Border::BORDER_DASHED;
132
133
            case Border::BORDER_DOUBLE:
134
                return Border::BORDER_DOUBLE;
135
136
            case Border::BORDER_HAIR:
137
            case Border::BORDER_MEDIUM:
138
            case Border::BORDER_THICK:
139
            case Border::BORDER_THIN:
140 1
                return 'solid';
141
        }
142
143
        return 'solid';
144
    }
145
146 43
    private function writeCellProperties(CellStyle $style): void
147
    {
148
        // Align
149 43
        $hAlign = $style->getAlignment()->getHorizontal();
150 43
        $hAlign = $this->mapHorizontalAlignment($hAlign);
151 43
        $vAlign = $style->getAlignment()->getVertical();
152 43
        $wrap = $style->getAlignment()->getWrapText();
153 43
        $indent = $style->getAlignment()->getIndent();
154
155 43
        $this->writer->startElement('style:table-cell-properties');
156 43
        if (!empty($vAlign) || $wrap) {
157 43
            if (!empty($vAlign)) {
158 43
                $vAlign = $this->mapVerticalAlignment($vAlign);
159 43
                $this->writer->writeAttribute('style:vertical-align', $vAlign);
160
            }
161 43
            if ($wrap) {
162 1
                $this->writer->writeAttribute('fo:wrap-option', 'wrap');
163
            }
164
        }
165 43
        $this->writer->writeAttribute('style:rotation-align', 'none');
166
167
        // Fill
168 43
        $this->writeFillStyle($style->getFill());
169
170
        // Border
171 43
        $this->writeBordersStyle($style->getBorders());
172
173 43
        $this->writer->endElement();
174
175 43
        if ($hAlign !== '' || !empty($indent)) {
176 1
            $this->writer
177 1
                ->startElement('style:paragraph-properties');
178 1
            if ($hAlign !== '') {
179
                $this->writer->writeAttribute('fo:text-align', $hAlign);
180
            }
181 1
            if (!empty($indent)) {
182 1
                $indentString = sprintf('%.4f', $indent * self::INDENT_TO_INCHES) . 'in';
183 1
                $this->writer->writeAttribute('fo:margin-left', $indentString);
184
            }
185 1
            $this->writer->endElement();
186
        }
187
    }
188
189 1
    protected function mapUnderlineStyle(Font $font): string
190
    {
191 1
        return match ($font->getUnderline()) {
192 1
            Font::UNDERLINE_DOUBLE, Font::UNDERLINE_DOUBLEACCOUNTING => 'double',
193 1
            Font::UNDERLINE_SINGLE, Font::UNDERLINE_SINGLEACCOUNTING => 'single',
194 1
            default => 'none',
195 1
        };
196
    }
197
198 43
    protected function writeTextProperties(CellStyle $style): void
199
    {
200
        // Font
201 43
        $this->writer->startElement('style:text-properties');
202
203 43
        $font = $style->getFont();
204
205 43
        if ($font->getBold()) {
206 3
            $this->writer->writeAttribute('fo:font-weight', 'bold');
207 3
            $this->writer->writeAttribute(
208 3
                'style:font-weight-complex',
209 3
                'bold'
210 3
            );
211 3
            $this->writer->writeAttribute(
212 3
                'style:font-weight-asian',
213 3
                'bold'
214 3
            );
215
        }
216
217 43
        if ($font->getItalic()) {
218 2
            $this->writer->writeAttribute('fo:font-style', 'italic');
219
        }
220
221 43
        if ($font->getAutoColor()) {
222 1
            $this->writer
223 1
                ->writeAttribute('style:use-window-font-color', 'true');
224
        } else {
225 42
            $this->writer->writeAttribute('fo:color', sprintf('#%s', $font->getColor()->getRGB()));
226
        }
227
228 43
        if ($family = $font->getName()) {
229 43
            $this->writer->writeAttribute('fo:font-family', $family);
230
        }
231
232 43
        if ($size = $font->getSize()) {
233 43
            $this->writer->writeAttribute('fo:font-size', sprintf('%.1Fpt', $size));
234
        }
235
236 43
        if ($font->getUnderline() && $font->getUnderline() !== Font::UNDERLINE_NONE) {
237 1
            $this->writer->writeAttribute('style:text-underline-style', 'solid');
238 1
            $this->writer->writeAttribute('style:text-underline-width', 'auto');
239 1
            $this->writer->writeAttribute('style:text-underline-color', 'font-color');
240
241 1
            $underline = $this->mapUnderlineStyle($font);
242 1
            $this->writer->writeAttribute('style:text-underline-type', $underline);
243
        }
244
245 43
        $this->writer->endElement(); // Close style:text-properties
246
    }
247
248 7
    protected function writeColumnProperties(ColumnDimension $columnDimension): void
249
    {
250 7
        $this->writer->startElement('style:table-column-properties');
251 7
        $this->writer->writeAttribute(
252 7
            'style:column-width',
253 7
            round($columnDimension->getWidth(Dimension::UOM_CENTIMETERS), 3) . 'cm'
254 7
        );
255 7
        $this->writer->writeAttribute('fo:break-before', 'auto');
256
257
        // End
258 7
        $this->writer->endElement(); // Close style:table-column-properties
259
    }
260
261 7
    public function writeColumnStyles(ColumnDimension $columnDimension, int $sheetId): void
262
    {
263 7
        $this->writer->startElement('style:style');
264 7
        $this->writer->writeAttribute('style:family', 'table-column');
265 7
        $this->writer->writeAttribute(
266 7
            'style:name',
267 7
            sprintf('%s_%d_%d', self::COLUMN_STYLE_PREFIX, $sheetId, $columnDimension->getColumnNumeric())
268 7
        );
269
270 7
        $this->writeColumnProperties($columnDimension);
271
272
        // End
273 7
        $this->writer->endElement(); // Close style:style
274
    }
275
276 1
    protected function writeRowProperties(RowDimension $rowDimension): void
277
    {
278 1
        $this->writer->startElement('style:table-row-properties');
279 1
        $this->writer->writeAttribute(
280 1
            'style:row-height',
281 1
            round($rowDimension->getRowHeight(Dimension::UOM_CENTIMETERS), 3) . 'cm'
282 1
        );
283 1
        $this->writer->writeAttribute('style:use-optimal-row-height', 'false');
284 1
        $this->writer->writeAttribute('fo:break-before', 'auto');
285
286
        // End
287 1
        $this->writer->endElement(); // Close style:table-row-properties
288
    }
289
290 1
    public function writeRowStyles(RowDimension $rowDimension, int $sheetId): void
291
    {
292 1
        $this->writer->startElement('style:style');
293 1
        $this->writer->writeAttribute('style:family', 'table-row');
294 1
        $this->writer->writeAttribute(
295 1
            'style:name',
296 1
            sprintf('%s_%d_%d', self::ROW_STYLE_PREFIX, $sheetId, $rowDimension->getRowIndex())
297 1
        );
298
299 1
        $this->writeRowProperties($rowDimension);
300
301
        // End
302 1
        $this->writer->endElement(); // Close style:style
303
    }
304
305 43
    public function writeTableStyle(Worksheet $worksheet, int $sheetId): void
306
    {
307 43
        $this->writer->startElement('style:style');
308 43
        $this->writer->writeAttribute('style:family', 'table');
309 43
        $this->writer->writeAttribute(
310 43
            'style:name',
311 43
            sprintf('%s%d', self::TABLE_STYLE_PREFIX, $sheetId)
312 43
        );
313 43
        $this->writer->writeAttribute('style:master-page-name', 'Default');
314
315 43
        $this->writer->startElement('style:table-properties');
316
317 43
        $this->writer->writeAttribute(
318 43
            'table:display',
319 43
            $worksheet->getSheetState() === Worksheet::SHEETSTATE_VISIBLE ? 'true' : 'false'
320 43
        );
321
322 43
        $this->writer->endElement(); // Close style:table-properties
323 43
        $this->writer->endElement(); // Close style:style
324
    }
325
326 43
    public function write(CellStyle $style): void
327
    {
328 43
        $this->writer->startElement('style:style');
329 43
        $this->writer->writeAttribute('style:name', self::CELL_STYLE_PREFIX . $style->getIndex());
330 43
        $this->writer->writeAttribute('style:family', 'table-cell');
331 43
        $this->writer->writeAttribute('style:parent-style-name', 'Default');
332
333
        // Alignment, fill colour, etc
334 43
        $this->writeCellProperties($style);
335
336
        // style:text-properties
337 43
        $this->writeTextProperties($style);
338
339
        // End
340 43
        $this->writer->endElement(); // Close style:style
341
    }
342
}
343