Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

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