Completed
Push — master ( b2dc0c...584121 )
by Adrien
03:33
created

StyleHelper::getFillsSectionContent()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 26
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 2

Importance

Changes 4
Bugs 0 Features 2
Metric Value
c 4
b 0
f 2
dl 0
loc 26
ccs 14
cts 14
cp 1
rs 8.8571
cc 2
eloc 13
nc 2
nop 0
crap 2
1
<?php
2
3
namespace Box\Spout\Writer\XLSX\Helper;
4
5
use Box\Spout\Writer\Common\Helper\AbstractStyleHelper;
6
use Box\Spout\Writer\Style\Color;
7
use Box\Spout\Writer\Style\Style;
8
9
/**
10
 * Class StyleHelper
11
 * This class provides helper functions to manage styles
12
 *
13
 * @package Box\Spout\Writer\XLSX\Helper
14
 */
15
class StyleHelper extends AbstractStyleHelper
16
{
17
    /**
18
     * @var array
19
     */
20
    protected $registeredFills = [];
21
22
    /**
23
     * @var array [STYLE_ID] => [FILL_ID] maps a style to a fill declaration
24
     */
25
    protected $styleIdToFillMappingTable = [];
26
27
    /**
28
     * Excel preserves two default fills with index 0 and 1
29
     * Since Excel is the dominant vendor - we play along here
30
     *
31
     * @var int The fill index counter for custom fills.
32
     */
33
    protected $fillIndex = 2;
34
35
    /**
36
     * XLSX specific operations on the registered styles
37
     *
38
     * @param \Box\Spout\Writer\Style\Style $style
39
     * @return \Box\Spout\Writer\Style\Style
40
     */
41 120
    public function registerStyle($style)
42
    {
43 120
        $registeredStyle = parent::registerStyle($style);
44 120
        $this->registerFill($registeredStyle);
45 120
        return $registeredStyle;
46
    }
47
48
    /**
49
     * Register a fill definition
50
     *
51
     * @param \Box\Spout\Writer\Style\Style $style
52
     */
53 120
    protected function registerFill($style)
54
    {
55 120
        $styleId = $style->getId();
56
57
        // Currently - only solid backgrounds are supported
58
        // so $backgroundColor is a scalar value (RGB Color)
59 120
        $backgroundColor = $style->getBackgroundColor();
60
61
        // We need to track the already registered background definitions
62 120
        if (isset($backgroundColor) && !isset($this->registeredFills[$backgroundColor])) {
63 3
            $this->registeredFills[$backgroundColor] = $styleId;
64 3
        }
65
66 120
        if (!isset($this->styleIdToFillMappingTable[$styleId])) {
67
            // The fillId maps a style to a fill declaration
68
            // When there is no background color definition - we default to 0
69 120
            $fillId = $backgroundColor !== null ? $this->fillIndex++ : 0;
70 120
            $this->styleIdToFillMappingTable[$styleId] = $fillId;
71 120
        }
72 120
    }
73
74
75
    /**
76
     * Returns the content of the "styles.xml" file, given a list of styles.
77
     *
78
     * @return string
79
     */
80 75
    public function getStylesXMLFileContent()
81
    {
82
        $content = <<<EOD
83
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
84
<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
85 75
EOD;
86
87 75
        $content .= $this->getFontsSectionContent();
88 75
        $content .= $this->getFillsSectionContent();
89 75
        $content .= $this->getBordersSectionContent();
90 75
        $content .= $this->getCellStyleXfsSectionContent();
91 75
        $content .= $this->getCellXfsSectionContent();
92 75
        $content .= $this->getCellStylesSectionContent();
93
94
        $content .= <<<EOD
95
</styleSheet>
96 75
EOD;
97
98 75
        return $content;
99
    }
100
101
    /**
102
     * Returns the content of the "<fonts>" section.
103
     *
104
     * @return string
105
     */
106 75
    protected function getFontsSectionContent()
107
    {
108 75
        $content = '<fonts count="' . count($this->styleIdToStyleMappingTable) . '">';
109
110
        /** @var \Box\Spout\Writer\Style\Style $style */
111 75
        foreach ($this->getRegisteredStyles() as $style) {
112 75
            $content .= '<font>';
113
114 75
            $content .= '<sz val="' . $style->getFontSize() . '"/>';
115 75
            $content .= '<color rgb="' . Color::toARGB($style->getFontColor()) . '"/>';
116 75
            $content .= '<name val="' . $style->getFontName() . '"/>';
117
118 75
            if ($style->isFontBold()) {
119 9
                $content .= '<b/>';
120 9
            }
121 75
            if ($style->isFontItalic()) {
122 3
                $content .= '<i/>';
123 3
            }
124 75
            if ($style->isFontUnderline()) {
125 3
                $content .= '<u/>';
126 3
            }
127 75
            if ($style->isFontStrikethrough()) {
128 3
                $content .= '<strike/>';
129 3
            }
130
131 75
            $content .= '</font>';
132 75
        }
133
134 75
        $content .= '</fonts>';
135
136 75
        return $content;
137
    }
138
139
    /**
140
     * Returns the content of the "<fills>" section.
141
     *
142
     * @return string
143
     */
144 75
    protected function getFillsSectionContent()
145
    {
146
        // Excel reserves two default fills
147 75
        $fillsCount = count($this->registeredFills) + 2;
148 75
        $content = sprintf('<fills count="%d">', $fillsCount);
149
150 75
        $content .= '<fill><patternFill patternType="none"/></fill>';
151 75
        $content .= '<fill><patternFill patternType="gray125"/></fill>';
152
153
        // The other fills are actually registered by setting a background color
154 75
        foreach ($this->registeredFills as $styleId) {
155
156
            /** @var Style $style */
157 3
            $style = $this->styleIdToStyleMappingTable[$styleId];
158
159 3
            $backgroundColor = $style->getBackgroundColor();
160 3
            $content .= sprintf(
161 3
                '<fill><patternFill patternType="solid"><fgColor rgb="%s"/></patternFill></fill>',
162
                $backgroundColor
163 3
            );
164 75
        }
165
166 75
        $content .= '</fills>';
167
168 75
        return $content;
169
    }
170
171
    /**
172
     * Returns the content of the "<borders>" section.
173
     *
174
     * @return string
175
     */
176 75
    protected function getBordersSectionContent()
177
    {
178 75
        $registeredStyles = $this->getRegisteredStyles();
179 75
        $registeredStylesCount = count($registeredStyles);
180
181 75
        $content = '<borders count="' . $registeredStylesCount . '">';
182
183
        /** @var \Box\Spout\Writer\Style\Style $style */
184 75
        foreach ($registeredStyles as $style) {
185 75
            $border = $style->getBorder();
186 75
            if ($border) {
187 6
                $content .= '<border>';
188
189
                // @link https://github.com/box/spout/issues/271
190 6
                $sortOrder = ['left', 'right', 'top', 'bottom'];
191
192 6
                foreach ($sortOrder as $partName) {
193 6
                    if ($border->hasPart($partName)) {
194
                        /** @var $part \Box\Spout\Writer\Style\BorderPart */
195 6
                        $part = $border->getPart($partName);
196 6
                        $content .= BorderHelper::serializeBorderPart($part);
197 6
                    }
198 6
                }
199
200 6
                $content .= '</border>';
201
202 6
            } else {
203 75
                $content .= '<border><left/><right/><top/><bottom/></border>';
204
            }
205 75
        }
206
207 75
        $content .= '</borders>';
208
209 75
        return $content;
210
    }
211
212
    /**
213
     * Returns the content of the "<cellStyleXfs>" section.
214
     *
215
     * @return string
216
     */
217 75
    protected function getCellStyleXfsSectionContent()
218
    {
219
        return <<<EOD
220
<cellStyleXfs count="1">
221
    <xf borderId="0" fillId="0" fontId="0" numFmtId="0"/>
222
</cellStyleXfs>
223 75
EOD;
224
    }
225
226
    /**
227
     * Returns the content of the "<cellXfs>" section.
228
     *
229
     * @return string
230
     */
231 75
    protected function getCellXfsSectionContent()
232
    {
233 75
        $registeredStyles = $this->getRegisteredStyles();
234
235 75
        $content = '<cellXfs count="' . count($registeredStyles) . '">';
236
237 75
        foreach ($registeredStyles as $style) {
238
239 75
            $styleId = $style->getId();
240 75
            $fillId = $this->styleIdToFillMappingTable[$styleId];
241
242 75
            $content .= '<xf numFmtId="0" fontId="' . $styleId . '" fillId="' . $fillId . '" borderId="' . $styleId . '" xfId="0"';
243
244 75
            if ($style->shouldApplyFont()) {
245 75
                $content .= ' applyFont="1"';
246 75
            }
247
248 75
            if ($style->shouldApplyBorder()) {
249 6
                $content .= ' applyBorder="1"';
250 6
            }
251
252 75
            if ($style->shouldWrapText()) {
253 6
                $content .= ' applyAlignment="1">';
254 6
                $content .= '<alignment wrapText="1"/>';
255 6
                $content .= '</xf>';
256 6
            } else {
257 75
                $content .= '/>';
258
            }
259 75
        }
260
261 75
        $content .= '</cellXfs>';
262
263 75
        return $content;
264
    }
265
266
    /**
267
     * Returns the content of the "<cellStyles>" section.
268
     *
269
     * @return string
270
     */
271 75
    protected function getCellStylesSectionContent()
272
    {
273
        return <<<EOD
274
<cellStyles count="1">
275
    <cellStyle builtinId="0" name="Normal" xfId="0"/>
276
</cellStyles>
277 75
EOD;
278
    }
279
}
280