Completed
Push — master ( 16a2f9...52312b )
by Adrien
02:04
created

StyleRegistry::getFormatIdForStyleId()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Box\Spout\Writer\XLSX\Manager\Style;
4
5
use Box\Spout\Common\Entity\Style\Style;
6
7
/**
8
 * Class StyleRegistry
9
 * Registry for all used styles
10
 */
11
class StyleRegistry extends \Box\Spout\Writer\Common\Manager\Style\StyleRegistry
12
{
13
    /**
14
     * @see https://msdn.microsoft.com/en-us/library/ff529597(v=office.12).aspx
15
     * @var array Mapping between built-in format and the associated numFmtId
16
     */
17
    protected static $builtinNumFormatToIdMapping = [
18
        'General' => 0,
19
        '0' => 1,
20
        '0.00' => 2,
21
        '#,##0' => 3,
22
        '#,##0.00' => 4,
23
        '$#,##0,\-$#,##0' => 5,
24
        '$#,##0,[Red]\-$#,##0' => 6,
25
        '$#,##0.00,\-$#,##0.00' => 7,
26
        '$#,##0.00,[Red]\-$#,##0.00' => 8,
27
        '0%' => 9,
28
        '0.00%' => 10,
29
        '0.00E+00' => 11,
30
        '# ?/?' => 12,
31
        '# ??/??' => 13,
32
        'mm-dd-yy' => 14,
33
        'd-mmm-yy' => 15,
34
        'd-mmm' => 16,
35
        'mmm-yy' => 17,
36
        'h:mm AM/PM' => 18,
37
        'h:mm:ss AM/PM' => 19,
38
        'h:mm' => 20,
39
        'h:mm:ss' => 21,
40
        'm/d/yy h:mm' => 22,
41
42
        '#,##0 ,(#,##0)' => 37,
43
        '#,##0 ,[Red](#,##0)' => 38,
44
        '#,##0.00,(#,##0.00)' => 39,
45
        '#,##0.00,[Red](#,##0.00)' => 40,
46
47
        '_("$"* #,##0.00_),_("$"* \(#,##0.00\),_("$"* "-"??_),_(@_)' => 44,
48
        'mm:ss' => 45,
49
        '[h]:mm:ss' => 46,
50
        'mm:ss.0' => 47,
51
52
        '##0.0E+0' => 48,
53
        '@' => 49,
54
55
        '[$-404]e/m/d' => 27,
56
        'm/d/yy' => 30,
57
        't0' => 59,
58
        't0.00' => 60,
59
        't#,##0' => 61,
60
        't#,##0.00' => 62,
61
        't0%' => 67,
62
        't0.00%' => 68,
63
        't# ?/?' => 69,
64
        't# ??/??' => 70,
65
    ];
66
67
    /**
68
     * @var array
69
     */
70
    protected $registeredFormats = [];
71
72
    /**
73
     * @var array [STYLE_ID] => [FORMAT_ID] maps a style to a format declaration
74
     */
75
    protected $styleIdToFormatsMappingTable = [];
76
77
    /**
78
     * If the numFmtId is lower than 0xA4 (164 in decimal)
79
     * then it's a built-in number format.
80
     * Since Excel is the dominant vendor - we play along here
81
     *
82
     * @var int The fill index counter for custom fills.
83
     */
84
    protected $formatIndex = 164;
85
86
    /**
87
     * @var array
88
     */
89
    protected $registeredFills = [];
90
91
    /**
92
     * @var array [STYLE_ID] => [FILL_ID] maps a style to a fill declaration
93
     */
94
    protected $styleIdToFillMappingTable = [];
95
96
    /**
97
     * Excel preserves two default fills with index 0 and 1
98
     * Since Excel is the dominant vendor - we play along here
99
     *
100
     * @var int The fill index counter for custom fills.
101
     */
102
    protected $fillIndex = 2;
103
104
    /**
105
     * @var array
106
     */
107
    protected $registeredBorders = [];
108
109
    /**
110
     * @var array [STYLE_ID] => [BORDER_ID] maps a style to a border declaration
111
     */
112
    protected $styleIdToBorderMappingTable = [];
113
114
    /**
115
     * XLSX specific operations on the registered styles
116
     *
117
     * @param Style $style
118
     * @return Style
119
     */
120 43
    public function registerStyle(Style $style)
121
    {
122 43
        $registeredStyle = parent::registerStyle($style);
123 43
        $this->registerFill($registeredStyle);
124 43
        $this->registerFormat($registeredStyle);
125 43
        $this->registerBorder($registeredStyle);
126
127 43
        return $registeredStyle;
128
    }
129
130
    /**
131
     * Register a format definition
132
     *
133
     * @param Style $style
134
     */
135 43
    protected function registerFormat(Style $style)
136
    {
137 43
        $styleId = $style->getId();
138
139 43
        $format = $style->getFormat();
140 43
        if ($format) {
141 2
            $isFormatRegistered = isset($this->registeredFormats[$format]);
142
143
            // We need to track the already registered format definitions
144 2
            if ($isFormatRegistered) {
145
                $registeredStyleId = $this->registeredFormats[$format];
146
                $registeredFormatId = $this->styleIdToFormatsMappingTable[$registeredStyleId];
147
                $this->styleIdToFormatsMappingTable[$styleId] = $registeredFormatId;
148
            } else {
149 2
                $this->registeredFormats[$format] = $styleId;
150
151 2
                $id = self::$builtinNumFormatToIdMapping[$format] ?? $this->formatIndex++;
152 2
                $this->styleIdToFormatsMappingTable[$styleId] = $id;
153
            }
154
        } else {
155
            // The formatId maps a style to a format declaration
156
            // When there is no format definition - we default to 0 ( General )
157 43
            $this->styleIdToFormatsMappingTable[$styleId] = 0;
158
        }
159 43
    }
160
161
    /**
162
     * @param int $styleId
163
     * @return int|null Format ID associated to the given style ID
164
     */
165 24
    public function getFormatIdForStyleId($styleId)
166
    {
167 24
        return $this->styleIdToFormatsMappingTable[$styleId] ?? null;
168
    }
169
170
    /**
171
     * Register a fill definition
172
     *
173
     * @param Style $style
174
     */
175 43
    private function registerFill(Style $style)
176
    {
177 43
        $styleId = $style->getId();
178
179
        // Currently - only solid backgrounds are supported
180
        // so $backgroundColor is a scalar value (RGB Color)
181 43
        $backgroundColor = $style->getBackgroundColor();
182
183 43
        if ($backgroundColor) {
184 4
            $isBackgroundColorRegistered = isset($this->registeredFills[$backgroundColor]);
185
186
            // We need to track the already registered background definitions
187 4
            if ($isBackgroundColorRegistered) {
188 3
                $registeredStyleId = $this->registeredFills[$backgroundColor];
189 3
                $registeredFillId = $this->styleIdToFillMappingTable[$registeredStyleId];
190 3
                $this->styleIdToFillMappingTable[$styleId] = $registeredFillId;
191
            } else {
192 4
                $this->registeredFills[$backgroundColor] = $styleId;
193 4
                $this->styleIdToFillMappingTable[$styleId] = $this->fillIndex++;
194
            }
195
        } else {
196
            // The fillId maps a style to a fill declaration
197
            // When there is no background color definition - we default to 0
198 43
            $this->styleIdToFillMappingTable[$styleId] = 0;
199
        }
200 43
    }
201
202
    /**
203
     * @param int $styleId
204
     * @return int|null Fill ID associated to the given style ID
205
     */
206 15
    public function getFillIdForStyleId($styleId)
207
    {
208 15
        return (isset($this->styleIdToFillMappingTable[$styleId])) ?
209 15
            $this->styleIdToFillMappingTable[$styleId] :
210 15
            null;
211
    }
212
213
    /**
214
     * Register a border definition
215
     *
216
     * @param Style $style
217
     */
218 43
    private function registerBorder(Style $style)
219
    {
220 43
        $styleId = $style->getId();
221
222 43
        if ($style->shouldApplyBorder()) {
223 5
            $border = $style->getBorder();
224 5
            $serializedBorder = serialize($border);
225
226 5
            $isBorderAlreadyRegistered = isset($this->registeredBorders[$serializedBorder]);
227
228 5
            if ($isBorderAlreadyRegistered) {
229 3
                $registeredStyleId = $this->registeredBorders[$serializedBorder];
230 3
                $registeredBorderId = $this->styleIdToBorderMappingTable[$registeredStyleId];
231 3
                $this->styleIdToBorderMappingTable[$styleId] = $registeredBorderId;
232
            } else {
233 5
                $this->registeredBorders[$serializedBorder] = $styleId;
234 5
                $this->styleIdToBorderMappingTable[$styleId] = count($this->registeredBorders);
235
            }
236
        } else {
237
            // If no border should be applied - the mapping is the default border: 0
238 43
            $this->styleIdToBorderMappingTable[$styleId] = 0;
239
        }
240 43
    }
241
242
    /**
243
     * @param int $styleId
244
     * @return int|null Fill ID associated to the given style ID
245
     */
246 15
    public function getBorderIdForStyleId($styleId)
247
    {
248 15
        return (isset($this->styleIdToBorderMappingTable[$styleId])) ?
249 15
            $this->styleIdToBorderMappingTable[$styleId] :
250 15
            null;
251
    }
252
253
    /**
254
     * @return array
255
     */
256 37
    public function getRegisteredFills()
257
    {
258 37
        return $this->registeredFills;
259
    }
260
261
    /**
262
     * @return array
263
     */
264 37
    public function getRegisteredBorders()
265
    {
266 37
        return $this->registeredBorders;
267
    }
268
269
    /**
270
     * @return array
271
     */
272 37
    public function getRegisteredFormats()
273
    {
274 37
        return $this->registeredFormats;
275
    }
276
}
277