PluginProbe
TablePress – Tables in WordPress made easy / 3.4
TablePress – Tables in WordPress made easy v3.4
3.4 3.3.4 3.3.3 3.3.2 3.3.1 trunk 1.12 1.14 1.9.2 2.0.4 2.1.7 2.1.8 2.2 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3 2.3.1 2.3.2 2.4 2.4.1 2.4.2 2.4.3 All 45 releases
tablepress / libraries / vendor / PhpSpreadsheet / Reader / Gnumeric / Styles.php

Styles.php in TablePress – Tables in WordPress made easy 3.4, at libraries/vendor/PhpSpreadsheet/Reader/Gnumeric/Styles.php

304 lines 10.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace TablePress\PhpOffice\PhpSpreadsheet\Reader\Gnumeric;
4
5 use TablePress\PhpOffice\PhpSpreadsheet\Cell\Coordinate;
6 use TablePress\PhpOffice\PhpSpreadsheet\Shared\Date;
7 use TablePress\PhpOffice\PhpSpreadsheet\Spreadsheet;
8 use TablePress\PhpOffice\PhpSpreadsheet\Style\Alignment;
9 use TablePress\PhpOffice\PhpSpreadsheet\Style\Border;
10 use TablePress\PhpOffice\PhpSpreadsheet\Style\Borders;
11 use TablePress\PhpOffice\PhpSpreadsheet\Style\Fill;
12 use TablePress\PhpOffice\PhpSpreadsheet\Style\Font;
13 use SimpleXMLElement;
14
15 class Styles
16 {
17 private Spreadsheet $spreadsheet;
18
19 protected bool $readDataOnly;
20
21 /**
22 * @deprecated 5.10.0 No longer used, replaced by const which is not user-accessible.
23 *
24 * @var array<string[]>
25 */
26 public static array $mappings = self::MAPPINGS;
27
28 /** @internal */
29 public const MAPPINGS = [
30 'borderStyle' => [
31 '0' => Border::BORDER_NONE,
32 '1' => Border::BORDER_THIN,
33 '2' => Border::BORDER_MEDIUM,
34 '3' => Border::BORDER_SLANTDASHDOT,
35 '4' => Border::BORDER_DASHED,
36 '5' => Border::BORDER_THICK,
37 '6' => Border::BORDER_DOUBLE,
38 '7' => Border::BORDER_DOTTED,
39 '8' => Border::BORDER_MEDIUMDASHED,
40 '9' => Border::BORDER_DASHDOT,
41 '10' => Border::BORDER_MEDIUMDASHDOT,
42 '11' => Border::BORDER_DASHDOTDOT,
43 '12' => Border::BORDER_MEDIUMDASHDOTDOT,
44 '13' => Border::BORDER_MEDIUMDASHDOTDOT,
45 ],
46 'fillType' => [
47 '1' => Fill::FILL_SOLID,
48 '2' => Fill::FILL_PATTERN_DARKGRAY,
49 '3' => Fill::FILL_PATTERN_MEDIUMGRAY,
50 '4' => Fill::FILL_PATTERN_LIGHTGRAY,
51 '5' => Fill::FILL_PATTERN_GRAY125,
52 '6' => Fill::FILL_PATTERN_GRAY0625,
53 '7' => Fill::FILL_PATTERN_DARKHORIZONTAL, // horizontal stripe
54 '8' => Fill::FILL_PATTERN_DARKVERTICAL, // vertical stripe
55 '9' => Fill::FILL_PATTERN_DARKDOWN, // diagonal stripe
56 '10' => Fill::FILL_PATTERN_DARKUP, // reverse diagonal stripe
57 '11' => Fill::FILL_PATTERN_DARKGRID, // diagonal crosshatch
58 '12' => Fill::FILL_PATTERN_DARKTRELLIS, // thick diagonal crosshatch
59 '13' => Fill::FILL_PATTERN_LIGHTHORIZONTAL,
60 '14' => Fill::FILL_PATTERN_LIGHTVERTICAL,
61 '15' => Fill::FILL_PATTERN_LIGHTUP,
62 '16' => Fill::FILL_PATTERN_LIGHTDOWN,
63 '17' => Fill::FILL_PATTERN_LIGHTGRID, // thin horizontal crosshatch
64 '18' => Fill::FILL_PATTERN_LIGHTTRELLIS, // thin diagonal crosshatch
65 ],
66 'horizontal' => [
67 '1' => Alignment::HORIZONTAL_GENERAL,
68 '2' => Alignment::HORIZONTAL_LEFT,
69 '4' => Alignment::HORIZONTAL_RIGHT,
70 '8' => Alignment::HORIZONTAL_CENTER,
71 '16' => Alignment::HORIZONTAL_CENTER_CONTINUOUS,
72 '32' => Alignment::HORIZONTAL_JUSTIFY,
73 '64' => Alignment::HORIZONTAL_CENTER_CONTINUOUS,
74 ],
75 'underline' => [
76 '1' => Font::UNDERLINE_SINGLE,
77 '2' => Font::UNDERLINE_DOUBLE,
78 '3' => Font::UNDERLINE_SINGLEACCOUNTING,
79 '4' => Font::UNDERLINE_DOUBLEACCOUNTING,
80 ],
81 'vertical' => [
82 '1' => Alignment::VERTICAL_TOP,
83 '2' => Alignment::VERTICAL_BOTTOM,
84 '4' => Alignment::VERTICAL_CENTER,
85 '8' => Alignment::VERTICAL_JUSTIFY,
86 ],
87 ];
88
89 public function __construct(Spreadsheet $spreadsheet, bool $readDataOnly)
90 {
91 $this->spreadsheet = $spreadsheet;
92 $this->readDataOnly = $readDataOnly;
93 }
94
95 public function read(SimpleXMLElement $sheet, int $maxRow, int $maxCol): void
96 {
97 if ($sheet->Styles->StyleRegion !== null) {
98 $this->readStyles($sheet->Styles->StyleRegion, $maxRow, $maxCol);
99 }
100 }
101
102 private function readStyles(SimpleXMLElement $styleRegion, int $maxRow, int $maxCol): void
103 {
104 foreach ($styleRegion as $style) {
105 $styleAttributes = $style->attributes();
106 if ($styleAttributes !== null && ($styleAttributes['startRow'] <= $maxRow) && ($styleAttributes['startCol'] <= $maxCol)) {
107 $cellRange = $this->readStyleRange($styleAttributes, $maxCol, $maxRow);
108
109 $styleAttributes = $style->Style->attributes();
110
111 /** @var mixed[][] */
112 $styleArray = [];
113 // We still set the number format mask for date/time values, even if readDataOnly is true
114 // so that we can identify whether a float is a float or a date value
115 $formatCode = $styleAttributes ? (string) $styleAttributes['Format'] : null;
116 if ($formatCode && Date::isDateTimeFormatCode($formatCode)) {
117 $styleArray['numberFormat']['formatCode'] = $formatCode;
118 }
119 if ($this->readDataOnly === false && $styleAttributes !== null) {
120 // If readDataOnly is false, we set all formatting information
121 $styleArray['numberFormat']['formatCode'] = $formatCode;
122 $styleArray = $this->readStyle($styleArray, $styleAttributes, $style);
123 }
124 /** @var mixed[][] $styleArray */
125 $this->spreadsheet
126 ->getActiveSheet()
127 ->getStyle($cellRange)
128 ->applyFromArray($styleArray);
129 }
130 }
131 }
132
133 /** @param mixed[][] $styleArray */
134 private function addBorderDiagonal(SimpleXMLElement $srssb, array &$styleArray): void
135 {
136 if (isset($srssb->Diagonal, $srssb->{'Rev-Diagonal'})) {
137 $styleArray['borders']['diagonal'] = self::parseBorderAttributes($srssb->Diagonal->attributes());
138 $styleArray['borders']['diagonalDirection'] = Borders::DIAGONAL_BOTH;
139 } elseif (isset($srssb->Diagonal)) {
140 $styleArray['borders']['diagonal'] = self::parseBorderAttributes($srssb->Diagonal->attributes());
141 $styleArray['borders']['diagonalDirection'] = Borders::DIAGONAL_UP;
142 } elseif (isset($srssb->{'Rev-Diagonal'})) {
143 $styleArray['borders']['diagonal'] = self::parseBorderAttributes($srssb->{'Rev-Diagonal'}->attributes());
144 $styleArray['borders']['diagonalDirection'] = Borders::DIAGONAL_DOWN;
145 }
146 }
147
148 /** @param mixed[][] $styleArray */
149 private function addBorderStyle(SimpleXMLElement $srssb, array &$styleArray, string $direction): void
150 {
151 $ucDirection = ucfirst($direction);
152 if (isset($srssb->$ucDirection)) {
153 // https://github.com/phpstan/phpstan/issues/14925
154 /** @var SimpleXMLElement */
155 $temp = $srssb->$ucDirection;
156 $styleArray['borders'][$direction] = self::parseBorderAttributes($temp->attributes());
157 }
158 }
159
160 private function calcRotation(SimpleXMLElement $styleAttributes): int
161 {
162 $rotation = (int) $styleAttributes->Rotation;
163 if ($rotation >= 270 && $rotation <= 360) {
164 $rotation -= 360;
165 }
166 $rotation = (abs($rotation) > 90) ? 0 : $rotation;
167
168 return $rotation;
169 }
170
171 /** @param array<array<mixed>|string> $styleArray */
172 private static function addStyle(array &$styleArray, string $key, string $value): void
173 {
174 if (array_key_exists($value, self::MAPPINGS[$key])) {
175 $styleArray[$key] = self::MAPPINGS[$key][$value];
176 }
177 }
178
179 /** @param mixed[][] $styleArray */
180 private static function addStyle2(array &$styleArray, string $key1, string $key, string $value): void
181 {
182 if (array_key_exists($value, self::MAPPINGS[$key])) {
183 $styleArray[$key1][$key] = self::MAPPINGS[$key][$value];
184 }
185 }
186
187 /** @return mixed[][] */
188 private static function parseBorderAttributes(?SimpleXMLElement $borderAttributes): array
189 {
190 /** @var mixed[][] */
191 $styleArray = [];
192 if ($borderAttributes !== null) {
193 if (isset($borderAttributes['Color'])) {
194 $styleArray['color']['rgb'] = self::parseGnumericColour($borderAttributes['Color']);
195 }
196
197 self::addStyle($styleArray, 'borderStyle', (string) $borderAttributes['Style']);
198 }
199 /** @var mixed[][] $styleArray */
200
201 return $styleArray;
202 }
203
204 private static function parseGnumericColour(string $gnmColour): string
205 {
206 [$gnmR, $gnmG, $gnmB] = explode(':', $gnmColour);
207 $gnmR = substr(str_pad($gnmR, 4, '0', STR_PAD_RIGHT), 0, 2);
208 $gnmG = substr(str_pad($gnmG, 4, '0', STR_PAD_RIGHT), 0, 2);
209 $gnmB = substr(str_pad($gnmB, 4, '0', STR_PAD_RIGHT), 0, 2);
210
211 return $gnmR . $gnmG . $gnmB;
212 }
213
214 /** @param mixed[][] $styleArray */
215 private function addColors(array &$styleArray, SimpleXMLElement $styleAttributes): void
216 {
217 $RGB = self::parseGnumericColour((string) $styleAttributes['Fore']);
218 /** @var mixed[][][] $styleArray */
219 $styleArray['font']['color']['rgb'] = $RGB;
220 $RGB = self::parseGnumericColour((string) $styleAttributes['Back']);
221 $shade = (string) $styleAttributes['Shade'];
222 if (($RGB !== '000000') || ($shade !== '0')) {
223 $RGB2 = self::parseGnumericColour((string) $styleAttributes['PatternColor']);
224 if ($shade === '1') {
225 $styleArray['fill']['startColor']['rgb'] = $RGB;
226 $styleArray['fill']['endColor']['rgb'] = $RGB2;
227 } else {
228 $styleArray['fill']['endColor']['rgb'] = $RGB;
229 $styleArray['fill']['startColor']['rgb'] = $RGB2;
230 }
231 self::addStyle2($styleArray, 'fill', 'fillType', $shade);
232 }
233 }
234
235 private function readStyleRange(SimpleXMLElement $styleAttributes, int $maxCol, int $maxRow): string
236 {
237 $startColumn = Coordinate::stringFromColumnIndex((int) $styleAttributes['startCol'] + 1);
238 $startRow = $styleAttributes['startRow'] + 1;
239
240 $endColumn = ($styleAttributes['endCol'] > $maxCol) ? $maxCol : (int) $styleAttributes['endCol'];
241 $endColumn = Coordinate::stringFromColumnIndex($endColumn + 1);
242
243 $endRow = 1 + (($styleAttributes['endRow'] > $maxRow) ? $maxRow : (int) $styleAttributes['endRow']);
244 $cellRange = $startColumn . $startRow . ':' . $endColumn . $endRow;
245
246 return $cellRange;
247 }
248
249 /**
250 * @param mixed[][] $styleArray
251 *
252 * @return mixed[]
253 */
254 private function readStyle(array $styleArray, SimpleXMLElement $styleAttributes, SimpleXMLElement $style): array
255 {
256 self::addStyle2($styleArray, 'alignment', 'horizontal', (string) $styleAttributes['HAlign']);
257 self::addStyle2($styleArray, 'alignment', 'vertical', (string) $styleAttributes['VAlign']);
258 $styleArray['alignment']['wrapText'] = $styleAttributes['WrapText'] == '1';
259 $styleArray['alignment']['textRotation'] = $this->calcRotation($styleAttributes);
260 $styleArray['alignment']['shrinkToFit'] = $styleAttributes['ShrinkToFit'] == '1';
261 $styleArray['alignment']['indent'] = ((int) ($styleAttributes['Indent']) > 0) ? $styleAttributes['indent'] : 0;
262
263 $this->addColors($styleArray, $styleAttributes);
264
265 $fontAttributes = $style->Style->Font->attributes();
266 if ($fontAttributes !== null) {
267 $styleArray['font']['name'] = (string) $style->Style->Font;
268 $styleArray['font']['size'] = (int) ($fontAttributes['Unit']);
269 $styleArray['font']['bold'] = $fontAttributes['Bold'] == '1';
270 $styleArray['font']['italic'] = $fontAttributes['Italic'] == '1';
271 $styleArray['font']['strikethrough'] = $fontAttributes['StrikeThrough'] == '1';
272 self::addStyle2($styleArray, 'font', 'underline', (string) $fontAttributes['Underline']);
273
274 switch ($fontAttributes['Script']) {
275 case '1':
276 $styleArray['font']['superscript'] = true;
277
278 break;
279 case '-1':
280 $styleArray['font']['subscript'] = true;
281
282 break;
283 }
284 }
285
286 if (isset($style->Style->StyleBorder)) {
287 $srssb = $style->Style->StyleBorder;
288 $this->addBorderStyle($srssb, $styleArray, 'top');
289 $this->addBorderStyle($srssb, $styleArray, 'bottom');
290 $this->addBorderStyle($srssb, $styleArray, 'left');
291 $this->addBorderStyle($srssb, $styleArray, 'right');
292 $this->addBorderDiagonal($srssb, $styleArray);
293 }
294 // TO DO
295 /*
296 if (isset($style->Style->HyperLink)) {
297 $hyperlink = $style->Style->HyperLink->attributes();
298 }
299 */
300
301 return $styleArray;
302 }
303 }
304