Failed Conditions
Pull Request — master (#3693)
by Franck
12:50
created

Style   F

Complexity

Total Complexity 60

Size/Duplication

Total Lines 302
Duplicated Lines 0 %

Test Coverage

Coverage 85.04%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 60
eloc 164
c 1
b 0
f 0
dl 0
loc 302
ccs 108
cts 127
cp 0.8504
rs 3.6

17 Methods

Rating   Name   Duplication   Size   Complexity  
C mapBorderWidth() 0 22 14
A mapVerticalAlignment() 0 7 1
A writeTableStyle() 0 18 2
A writeBorderStyle() 0 11 2
A writeCellProperties() 0 32 6
A writeColumnStyles() 0 13 1
A write() 0 15 1
C mapBorderStyle() 0 26 14
A writeRowStyles() 0 13 1
A __construct() 0 3 1
A writeBordersStyle() 0 6 1
A writeRowProperties() 0 12 1
A mapHorizontalAlignment() 0 7 1
A writeColumnProperties() 0 11 1
A mapUnderlineStyle() 0 6 1
B writeTextProperties() 0 37 7
A writeFillStyle() 0 16 5

How to fix   Complexity   

Complex Class

Complex classes like Style often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Style, and based on these observations, apply Extract Interface, too.

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