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 / Style / Style.php

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

806 lines 24.0 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\Style;
4
5 use TablePress\PhpOffice\PhpSpreadsheet\Calculation\Functions;
6 use TablePress\PhpOffice\PhpSpreadsheet\Cell\AddressRange;
7 use TablePress\PhpOffice\PhpSpreadsheet\Cell\Coordinate;
8 use TablePress\PhpOffice\PhpSpreadsheet\Chart\ChartColor;
9 use TablePress\PhpOffice\PhpSpreadsheet\Exception;
10 use TablePress\PhpOffice\PhpSpreadsheet\Shared\StringHelper;
11 use TablePress\PhpOffice\PhpSpreadsheet\Spreadsheet;
12 use TablePress\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
13
14 class Style extends Supervisor
15 {
16 /**
17 * Font.
18 */
19 protected Font $font;
20
21 /**
22 * Fill.
23 */
24 protected Fill $fill;
25
26 /**
27 * Borders.
28 */
29 protected Borders $borders;
30
31 /**
32 * Alignment.
33 */
34 protected Alignment $alignment;
35
36 /**
37 * Number Format.
38 */
39 protected NumberFormat $numberFormat;
40
41 /**
42 * Protection.
43 */
44 protected Protection $protection;
45
46 /**
47 * Index of style in collection. Only used for real style.
48 */
49 protected int $index;
50
51 /**
52 * Use Quote Prefix when displaying in cell editor. Only used for real style.
53 */
54 protected bool $quotePrefix = false;
55
56 protected bool $checkBox = false;
57
58 /**
59 * Internal cache for styles
60 * Used when applying style on range of cells (column or row) and cleared when
61 * all cells in range is styled.
62 *
63 * PhpSpreadsheet will always minimize the amount of styles used. So cells with
64 * same styles will reference the same Style instance. To check if two styles
65 * are similar Style::getHashCode() is used. This call is expensive. To minimize
66 * the need to call this method we can cache the internal PHP object id of the
67 * Style in the range. Style::getHashCode() will then only be called when we
68 * encounter a unique style.
69 *
70 * @see Style::applyFromArray()
71 * @see Style::getHashCode()
72 *
73 * @var null|array<string, mixed[]>
74 */
75 private static ?array $cachedStyles = null;
76
77 /**
78 * Create a new Style.
79 *
80 * @param bool $isSupervisor Flag indicating if this is a supervisor or not
81 * Leave this value at default unless you understand exactly what
82 * its ramifications are
83 * @param bool $isConditional Flag indicating if this is a conditional style or not
84 * Leave this value at default unless you understand exactly what
85 * its ramifications are
86 */
87 public function __construct(bool $isSupervisor = false, bool $isConditional = false)
88 {
89 parent::__construct($isSupervisor);
90
91 // Initialise values
92 $this->font = new Font($isSupervisor, $isConditional);
93 $this->fill = new Fill($isSupervisor, $isConditional);
94 $this->borders = new Borders($isSupervisor, $isConditional);
95 $this->alignment = new Alignment($isSupervisor, $isConditional);
96 $this->numberFormat = new NumberFormat($isSupervisor, $isConditional);
97 $this->protection = new Protection($isSupervisor, $isConditional);
98
99 // bind parent if we are a supervisor
100 if ($isSupervisor) {
101 $this->font->bindParent($this);
102 $this->fill->bindParent($this);
103 $this->borders->bindParent($this);
104 $this->alignment->bindParent($this);
105 $this->numberFormat->bindParent($this);
106 $this->protection->bindParent($this);
107 }
108 }
109
110 /**
111 * Get the shared style component for the currently active cell in currently active sheet.
112 * Only used for style supervisor.
113 */
114 public function getSharedComponent(): self
115 {
116 $activeSheet = $this->getActiveSheet();
117 $selectedCell = Functions::trimSheetFromCellReference($this->getActiveCell()); // e.g. 'A1'
118
119 if ($activeSheet->cellExists($selectedCell)) {
120 $xfIndex = $activeSheet->getCell($selectedCell)->getXfIndex();
121 } else {
122 $xfIndex = 0;
123 }
124
125 return $activeSheet->getParentOrThrow()->getCellXfByIndex($xfIndex);
126 }
127
128 /**
129 * Get parent. Only used for style supervisor.
130 */
131 public function getParent(): Spreadsheet
132 {
133 return $this->getActiveSheet()->getParentOrThrow();
134 }
135
136 private const REGEX_WHOLE_COLUMN = '/^[A-Z]+1:[A-Z]+'
137 . AddressRange::MAX_ROW
138 . '$/';
139 private const REGEX_WHOLE_ROW = '/^A\d+:'
140 . AddressRange::MAX_COLUMN
141 . '\d+$/';
142
143 /**
144 * Build style array from subcomponents.
145 *
146 * @param mixed[] $array
147 *
148 * @return array{quotePrefix: mixed[]}
149 */
150 public function getStyleArray(array $array): array
151 {
152 return ['quotePrefix' => $array];
153 }
154
155 /**
156 * Apply styles from array.
157 *
158 * <code>
159 * $spreadsheet->getActiveSheet()->getStyle('B2')->applyFromArray(
160 * [
161 * 'font' => [
162 * 'name' => 'Arial',
163 * 'bold' => true,
164 * 'italic' => false,
165 * 'underline' => Font::UNDERLINE_DOUBLE,
166 * 'strikethrough' => false,
167 * 'color' => [
168 * 'rgb' => '808080'
169 * ]
170 * ],
171 * 'borders' => [
172 * 'bottom' => [
173 * 'borderStyle' => Border::BORDER_DASHDOT,
174 * 'color' => [
175 * 'rgb' => '808080'
176 * ]
177 * ],
178 * 'top' => [
179 * 'borderStyle' => Border::BORDER_DASHDOT,
180 * 'color' => [
181 * 'rgb' => '808080'
182 * ]
183 * ]
184 * ],
185 * 'alignment' => [
186 * 'horizontal' => Alignment::HORIZONTAL_CENTER,
187 * 'vertical' => Alignment::VERTICAL_CENTER,
188 * 'wrapText' => true,
189 * ],
190 * 'quotePrefix' => true
191 * ]
192 * );
193 * </code>
194 *
195 * @param mixed[] $styleArray Array containing style information
196 * @param bool $advancedBorders advanced mode for setting borders
197 *
198 * @return $this
199 */
200 public function applyFromArray(array $styleArray, bool $advancedBorders = true)
201 {
202 if ($this->isSupervisor) {
203 $pRange = $this->getSelectedCells();
204 if (str_contains($pRange, ',')) {
205 $ranges = explode(',', $pRange);
206 $sheet = $this->getActiveSheet();
207 foreach ($ranges as $range) {
208 $sheet
209 ->setSelectedCells(trim($range));
210 $this->applyFromArray($styleArray, $advancedBorders);
211 }
212 $sheet->setSelectedCells($pRange);
213
214 return $this;
215 }
216
217 // Uppercase coordinate and strip any Worksheet reference from the selected range
218 $pRange = strtoupper($pRange);
219 if (str_contains($pRange, '!')) {
220 $pRangeWorksheet = StringHelper::strToUpper((string) substr($pRange, 0, (int) strrpos($pRange, '!')));
221 $pRangeWorksheet = Worksheet::unApostrophizeTitle($pRangeWorksheet);
222 if ($pRangeWorksheet !== '' && StringHelper::strToUpper($this->getActiveSheet()->getTitle()) !== $pRangeWorksheet) {
223 throw new Exception('Invalid Worksheet for specified Range');
224 }
225 $pRange = strtoupper(Functions::trimSheetFromCellReference($pRange));
226 }
227
228 // Is it a cell range or a single cell?
229 if (!str_contains($pRange, ':')) {
230 $rangeA = $pRange;
231 $rangeB = $pRange;
232 } else {
233 [$rangeA, $rangeB] = explode(':', $pRange);
234 }
235
236 // Calculate range outer borders
237 $rangeStart = Coordinate::coordinateFromString($rangeA);
238 $rangeEnd = Coordinate::coordinateFromString($rangeB);
239 $rangeStartIndexes = Coordinate::indexesFromString($rangeA);
240 $rangeEndIndexes = Coordinate::indexesFromString($rangeB);
241
242 $columnStart = $rangeStart[0];
243 $columnEnd = $rangeEnd[0];
244
245 // Make sure we can loop upwards on rows and columns
246 if ($rangeStartIndexes[0] > $rangeEndIndexes[0] && $rangeStartIndexes[1] > $rangeEndIndexes[1]) {
247 $tmp = $rangeStartIndexes;
248 $rangeStartIndexes = $rangeEndIndexes;
249 $rangeEndIndexes = $tmp;
250 }
251
252 // ADVANCED MODE:
253 if ($advancedBorders && isset($styleArray['borders'])) {
254 // 'allBorders' is a shorthand property for 'outline' and 'inside' and
255 // it applies to components that have not been set explicitly
256 /** @var mixed[][] $styleArray */
257 if (isset($styleArray['borders']['allBorders'])) {
258 foreach (['outline', 'inside'] as $component) {
259 if (!isset($styleArray['borders'][$component])) {
260 $styleArray['borders'][$component] = $styleArray['borders']['allBorders'];
261 }
262 }
263 unset($styleArray['borders']['allBorders']); // not needed any more
264 }
265 // 'outline' is a shorthand property for 'top', 'right', 'bottom', 'left'
266 // it applies to components that have not been set explicitly
267 if (isset($styleArray['borders']['outline'])) {
268 foreach (['top', 'right', 'bottom', 'left'] as $component) {
269 if (!isset($styleArray['borders'][$component])) {
270 $styleArray['borders'][$component] = $styleArray['borders']['outline'];
271 }
272 }
273 unset($styleArray['borders']['outline']); // not needed any more
274 }
275 // 'inside' is a shorthand property for 'vertical' and 'horizontal'
276 // it applies to components that have not been set explicitly
277 if (isset($styleArray['borders']['inside'])) {
278 foreach (['vertical', 'horizontal'] as $component) {
279 if (!isset($styleArray['borders'][$component])) {
280 $styleArray['borders'][$component] = $styleArray['borders']['inside'];
281 }
282 }
283 unset($styleArray['borders']['inside']); // not needed any more
284 }
285 // width and height characteristics of selection, 1, 2, or 3 (for 3 or more)
286 $xMax = min($rangeEndIndexes[0] - $rangeStartIndexes[0] + 1, 3);
287 $yMax = min($rangeEndIndexes[1] - $rangeStartIndexes[1] + 1, 3);
288
289 // loop through up to 3 x 3 = 9 regions
290 for ($x = 1; $x <= $xMax; ++$x) {
291 // start column index for region
292 $colStart = ($x == 3)
293 ? Coordinate::stringFromColumnIndex($rangeEndIndexes[0])
294 : Coordinate::stringFromColumnIndex($rangeStartIndexes[0] + $x - 1);
295 // end column index for region
296 $colEnd = ($x == 1)
297 ? Coordinate::stringFromColumnIndex($rangeStartIndexes[0])
298 : Coordinate::stringFromColumnIndex($rangeEndIndexes[0] - $xMax + $x);
299
300 for ($y = 1; $y <= $yMax; ++$y) {
301 // which edges are touching the region
302 $edges = [];
303 if ($x == 1) {
304 // are we at left edge
305 $edges[] = 'left';
306 }
307 if ($x == $xMax) {
308 // are we at right edge
309 $edges[] = 'right';
310 }
311 if ($y == 1) {
312 // are we at top edge?
313 $edges[] = 'top';
314 }
315 if ($y == $yMax) {
316 // are we at bottom edge?
317 $edges[] = 'bottom';
318 }
319
320 // start row index for region
321 $rowStart = ($y == 3)
322 ? $rangeEndIndexes[1] : $rangeStartIndexes[1] + $y - 1;
323
324 // end row index for region
325 $rowEnd = ($y == 1)
326 ? $rangeStartIndexes[1] : $rangeEndIndexes[1] - $yMax + $y;
327
328 // build range for region
329 $range = $colStart . $rowStart . ':' . $colEnd . $rowEnd;
330
331 // retrieve relevant style array for region
332 $regionStyles = $styleArray;
333 unset($regionStyles['borders']['inside']);
334
335 // what are the inner edges of the region when looking at the selection
336 $innerEdges = array_diff(['top', 'right', 'bottom', 'left'], $edges);
337
338 // inner edges that are not touching the region should take the 'inside' border properties if they have been set
339 foreach ($innerEdges as $innerEdge) {
340 switch ($innerEdge) {
341 case 'top':
342 case 'bottom':
343 /** @var mixed[][] $styleArray */
344 // should pick up 'horizontal' border property if set
345 if (isset($styleArray['borders']['horizontal'])) {
346 /** @var mixed[][] $regionStyles */
347 $regionStyles['borders'][$innerEdge]
348 = $styleArray['borders']['horizontal'];
349 } else {
350 /** @var mixed[][] $regionStyles */
351 unset($regionStyles['borders'][$innerEdge]);
352 }
353
354 break;
355 case 'left':
356 case 'right':
357 // should pick up 'vertical' border property if set
358 if (isset($styleArray['borders']['vertical'])) {
359 $regionStyles['borders'][$innerEdge] = $styleArray['borders']['vertical'];
360 } else {
361 unset($regionStyles['borders'][$innerEdge]);
362 }
363
364 break;
365 }
366 }
367
368 // apply region style to region by calling applyFromArray() in simple mode
369 $this->getActiveSheet()->getStyle($range)->applyFromArray($regionStyles, false);
370 }
371 }
372
373 // restore initial cell selection range
374 $this->getActiveSheet()->getStyle($pRange);
375
376 return $this;
377 }
378
379 // SIMPLE MODE:
380 // Selection type, inspect
381 if (preg_match(self::REGEX_WHOLE_COLUMN, $pRange)) {
382 $selectionType = 'COLUMN';
383
384 // Enable caching of styles
385 self::$cachedStyles = ['hashByObjId' => [], 'styleByHash' => []];
386 } elseif (preg_match(self::REGEX_WHOLE_ROW, $pRange)) {
387 $selectionType = 'ROW';
388
389 // Enable caching of styles
390 self::$cachedStyles = ['hashByObjId' => [], 'styleByHash' => []];
391 } else {
392 $selectionType = 'CELL';
393 }
394
395 // First loop through columns, rows, or cells to find out which styles are affected by this operation
396 $oldXfIndexes = $this->getOldXfIndexes($selectionType, $rangeStartIndexes, $rangeEndIndexes, $columnStart, $columnEnd, $styleArray);
397
398 // clone each of the affected styles, apply the style array, and add the new styles to the workbook
399 $workbook = $this->getActiveSheet()->getParentOrThrow();
400 $newXfIndexes = [];
401 foreach ($oldXfIndexes as $oldXfIndex => $dummy) {
402 $style = $workbook->getCellXfByIndex($oldXfIndex);
403
404 // $cachedStyles is set when applying style for a range of cells, either column or row
405 if (self::$cachedStyles === null) {
406 // Clone the old style and apply style-array
407 $newStyle = clone $style;
408 $newStyle->applyFromArray($styleArray);
409
410 // Look for existing style we can use instead (reduce memory usage)
411 $existingStyle = $workbook->getCellXfByHashCode($newStyle->getHashCode());
412 } else {
413 // Style cache is stored by Style::getHashCode(). But calling this method is
414 // expensive. So we cache the php obj id -> hash.
415 $objId = spl_object_id($style);
416
417 // Look for the original HashCode
418 $styleHash = self::$cachedStyles['hashByObjId'][$objId] ?? null;
419 if ($styleHash === null) {
420 // This object_id is not cached, store the hashcode in case encounter again
421 $styleHash = self::$cachedStyles['hashByObjId'][$objId] = $style->getHashCode();
422 }
423
424 // Find existing style by hash.
425 /** @var string $styleHash */
426 $existingStyle = self::$cachedStyles['styleByHash'][$styleHash] ?? null;
427
428 if (!$existingStyle) {
429 // The old style combined with the new style array is not cached, so we create it now
430 $newStyle = clone $style;
431 $newStyle->applyFromArray($styleArray);
432
433 // Look for similar style in workbook to reduce memory usage
434 $existingStyle = $workbook->getCellXfByHashCode($newStyle->getHashCode());
435
436 // Cache the new style by original hashcode
437 self::$cachedStyles['styleByHash'][$styleHash] = $existingStyle instanceof self ? $existingStyle : $newStyle;
438 }
439 }
440
441 if ($existingStyle) {
442 // there is already such cell Xf in our collection
443 /** @var Style $existingStyle */
444 $newXfIndexes[$oldXfIndex] = $existingStyle->getIndex();
445 } else {
446 if (!isset($newStyle)) {
447 // Handle bug in PHPStan, see https://github.com/phpstan/phpstan/issues/5805
448 // $newStyle should always be defined.
449 // This block might not be needed in the future
450 // @codeCoverageIgnoreStart
451 $newStyle = clone $style;
452 $newStyle->applyFromArray($styleArray);
453 // @codeCoverageIgnoreEnd
454 }
455
456 // we don't have such a cell Xf, need to add
457 $workbook->addCellXf($newStyle);
458 $newXfIndexes[$oldXfIndex] = $newStyle->getIndex();
459 }
460 }
461
462 // Loop through columns, rows, or cells again and update the XF index
463 switch ($selectionType) {
464 case 'COLUMN':
465 for ($col = $rangeStartIndexes[0]; $col <= $rangeEndIndexes[0]; ++$col) {
466 $columnDimension = $this->getActiveSheet()->getColumnDimensionByColumn($col);
467 $oldXfIndex = $columnDimension->getXfIndex();
468 /** @var int[] $newXfIndexes */
469 $columnDimension->setXfIndex($newXfIndexes[$oldXfIndex]);
470 }
471
472 // Disable caching of styles
473 self::$cachedStyles = null;
474
475 break;
476 case 'ROW':
477 for ($row = $rangeStartIndexes[1]; $row <= $rangeEndIndexes[1]; ++$row) {
478 $rowDimension = $this->getActiveSheet()->getRowDimension($row);
479 // row without explicit style should be formatted based on default style
480 $oldXfIndex = $rowDimension->getXfIndex() ?? 0;
481 /** @var int[] $newXfIndexes */
482 $rowDimension->setXfIndex($newXfIndexes[$oldXfIndex]);
483 }
484
485 // Disable caching of styles
486 self::$cachedStyles = null;
487
488 break;
489 case 'CELL':
490 for ($col = $rangeStartIndexes[0]; $col <= $rangeEndIndexes[0]; ++$col) {
491 for ($row = $rangeStartIndexes[1]; $row <= $rangeEndIndexes[1]; ++$row) {
492 $cell = $this->getActiveSheet()->getCell([$col, $row]);
493 $oldXfIndex = $cell->getXfIndex();
494 $cell->setXfIndex($newXfIndexes[$oldXfIndex]);
495 }
496 }
497
498 break;
499 }
500 } else {
501 // not a supervisor, just apply the style array directly on style object
502 /** @var array{
503 * alignment?: mixed[],
504 * fill?: array{fillType?: string, rotation?: float, startColor?: array{rgb?: string, argb?: string}, endColor?: array{rgb?: string, argb?: string}, color?: array{rgb?: string, argb?: string}},
505 * font?: array{name?: string, latin?: string, eastAsian?: string, complexScript?: string, bold?: bool, italic?: bool, superscript?: bool, subscript?: bool, underline?: bool|string, strikethrough?: bool, color?: string[], size?: ?int, chartColor?: ChartColor, scheme?: string, cap?: string},
506 * borders?: mixed[][],
507 * numberFormat?: string[],
508 * protection?: array{locked?: string, hidden?: string},
509 * checkBox?: bool,
510 * quotePrefix?: bool} $styleArray */
511 if (isset($styleArray['checkBox'])) {
512 $this->checkBox = (bool) $styleArray['checkBox'];
513 }
514 if (isset($styleArray['fill'])) {
515 $this->getFill()
516 ->applyFromArray($styleArray['fill']);
517 }
518 if (isset($styleArray['font'])) {
519 $this->getFont()
520 ->applyFromArray($styleArray['font']);
521 }
522 if (isset($styleArray['borders'])) {
523 $this->getBorders()
524 ->applyFromArray($styleArray['borders']);
525 }
526 if (isset($styleArray['alignment'])) {
527 $temp = $styleArray['alignment'];
528 $this->getAlignment()
529 ->applyFromArray($temp);
530 }
531 if (isset($styleArray['numberFormat'])) {
532 $this->getNumberFormat()
533 ->applyFromArray($styleArray['numberFormat']);
534 }
535 if (isset($styleArray['protection'])) {
536 $this->getProtection()
537 ->applyFromArray($styleArray['protection']);
538 }
539 if (isset($styleArray['quotePrefix'])) {
540 $this->quotePrefix = $styleArray['quotePrefix'];
541 }
542 }
543
544 return $this;
545 }
546
547 /**
548 * @param mixed[] $rangeStart
549 * @param mixed[] $rangeEnd
550 * @param mixed[] $styleArray
551 *
552 * @return mixed[]
553 */
554 private function getOldXfIndexes(string $selectionType, array $rangeStart, array $rangeEnd, string $columnStart, string $columnEnd, array $styleArray): array
555 {
556 $oldXfIndexes = [];
557 switch ($selectionType) {
558 case 'COLUMN':
559 for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) {
560 /** @var int $col */
561 $oldXfIndexes[$this->getActiveSheet()->getColumnDimensionByColumn($col)->getXfIndex()] = true;
562 }
563 foreach ($this->getActiveSheet()->getColumnIterator($columnStart, $columnEnd) as $columnIterator) {
564 $cellIterator = $columnIterator->getCellIterator();
565 $cellIterator->setIterateOnlyExistingCells(true);
566 foreach ($cellIterator as $columnCell) {
567 $columnCell->getStyle()
568 ->applyFromArray($styleArray);
569 }
570 }
571
572 break;
573 case 'ROW':
574 for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) {
575 /** @var int $row */
576 if ($this->getActiveSheet()->getRowDimension($row)->getXfIndex() === null) {
577 $oldXfIndexes[0] = true; // row without explicit style should be formatted based on default style
578 } else {
579 $oldXfIndexes[$this->getActiveSheet()->getRowDimension($row)->getXfIndex()] = true;
580 }
581 }
582 /** @var float|int */
583 $temp1 = $rangeStart[1];
584 /** @var float|int */
585 $temp2 = $rangeEnd[1];
586 foreach ($this->getActiveSheet()->getRowIterator((int) $temp1, (int) $temp2) as $rowIterator) {
587 $cellIterator = $rowIterator->getCellIterator();
588 $cellIterator->setIterateOnlyExistingCells(true);
589 foreach ($cellIterator as $rowCell) {
590 $rowCell->getStyle()
591 ->applyFromArray($styleArray);
592 }
593 }
594
595 break;
596 case 'CELL':
597 for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) {
598 /** @var int $col */
599 for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) {
600 /** @var int $row */
601 $oldXfIndexes[$this->getActiveSheet()->getCell([$col, $row])->getXfIndex()] = true;
602 }
603 }
604
605 break;
606 }
607
608 return $oldXfIndexes;
609 }
610
611 /**
612 * Get Fill.
613 */
614 public function getFill(): Fill
615 {
616 return $this->fill;
617 }
618
619 /**
620 * Get Font.
621 */
622 public function getFont(): Font
623 {
624 return $this->font;
625 }
626
627 /**
628 * Set font.
629 *
630 * @return $this
631 */
632 public function setFont(Font $font)
633 {
634 $this->font = $font;
635
636 return $this;
637 }
638
639 /**
640 * Get Borders.
641 */
642 public function getBorders(): Borders
643 {
644 return $this->borders;
645 }
646
647 /**
648 * Get Alignment.
649 */
650 public function getAlignment(): Alignment
651 {
652 return $this->alignment;
653 }
654
655 /**
656 * Get Number Format.
657 */
658 public function getNumberFormat(): NumberFormat
659 {
660 return $this->numberFormat;
661 }
662
663 /**
664 * Get Conditional Styles. Only used on supervisor.
665 *
666 * @return Conditional[]
667 */
668 public function getConditionalStyles(): array
669 {
670 return $this->getActiveSheet()->getConditionalStyles($this->getActiveCell());
671 }
672
673 /**
674 * Set Conditional Styles. Only used on supervisor.
675 *
676 * @param Conditional[] $conditionalStyleArray Array of conditional styles
677 *
678 * @return $this
679 */
680 public function setConditionalStyles(array $conditionalStyleArray)
681 {
682 $this->getActiveSheet()->setConditionalStyles($this->getSelectedCells(), $conditionalStyleArray);
683
684 return $this;
685 }
686
687 /**
688 * Get Protection.
689 */
690 public function getProtection(): Protection
691 {
692 return $this->protection;
693 }
694
695 /**
696 * Get quote prefix.
697 */
698 public function getQuotePrefix(): bool
699 {
700 if ($this->isSupervisor) {
701 return $this->getSharedComponent()->getQuotePrefix();
702 }
703
704 return $this->quotePrefix;
705 }
706
707 /**
708 * Set quote prefix.
709 *
710 * @return $this
711 */
712 public function setQuotePrefix(bool $quotePrefix)
713 {
714 if ($quotePrefix == '') {
715 $quotePrefix = false;
716 }
717 if ($this->isSupervisor) {
718 $styleArray = ['quotePrefix' => $quotePrefix];
719 $this->getActiveSheet()
720 ->getStyle($this->getSelectedCells())
721 ->applyFromArray($styleArray);
722 } else {
723 $this->quotePrefix = (bool) $quotePrefix;
724 }
725
726 return $this;
727 }
728
729 public function getCheckBox(): bool
730 {
731 if ($this->isSupervisor) {
732 return $this->getSharedComponent()->getCheckBox();
733 }
734
735 return $this->checkBox;
736 }
737
738 /**
739 * @return static
740 */
741 public function setCheckBox(bool $checkBox)
742 {
743 if ($this->isSupervisor) {
744 $styleArray = ['checkBox' => $checkBox];
745 $this->getActiveSheet()
746 ->getStyle($this->getSelectedCells())
747 ->applyFromArray($styleArray);
748 } else {
749 $this->checkBox = $checkBox;
750 }
751
752 return $this;
753 }
754
755 /**
756 * Get hash code.
757 *
758 * @return string Hash code
759 */
760 public function getHashCode(): string
761 {
762 return md5(
763 $this->fill->getHashCode()
764 . $this->font->getHashCode()
765 . $this->borders->getHashCode()
766 . $this->alignment->getHashCode()
767 . $this->numberFormat->getHashCode()
768 . $this->protection->getHashCode()
769 . ($this->quotePrefix ? 't' : 'f')
770 . ($this->checkBox ? 't' : 'f')
771 . __CLASS__
772 );
773 }
774
775 /**
776 * Get own index in style collection.
777 */
778 public function getIndex(): int
779 {
780 return $this->index;
781 }
782
783 /**
784 * Set own index in style collection.
785 */
786 public function setIndex(int $index): void
787 {
788 $this->index = $index;
789 }
790
791 /** @return mixed[] */
792 protected function exportArray1(): array
793 {
794 $exportedArray = [];
795 $this->exportArray2($exportedArray, 'alignment', $this->getAlignment());
796 $this->exportArray2($exportedArray, 'borders', $this->getBorders());
797 $this->exportArray2($exportedArray, 'fill', $this->getFill());
798 $this->exportArray2($exportedArray, 'font', $this->getFont());
799 $this->exportArray2($exportedArray, 'numberFormat', $this->getNumberFormat());
800 $this->exportArray2($exportedArray, 'protection', $this->getProtection());
801 $this->exportArray2($exportedArray, 'quotePrefix', $this->getQuotePrefix());
802
803 return $exportedArray;
804 }
805 }
806