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