| 1 |
<?php |
| 2 |
|
| 3 |
namespace Box\Spout\Writer\Common\Helper; |
| 4 |
|
| 5 |
/** |
| 6 |
* Class AbstractStyleHelper |
| 7 |
* This class provides helper functions to manage styles |
| 8 |
* |
| 9 |
* @package Box\Spout\Writer\Common\Helper |
| 10 |
*/ |
| 11 |
abstract class AbstractStyleHelper |
| 12 |
{ |
| 13 |
/** @var array [SERIALIZED_STYLE] => [STYLE_ID] mapping table, keeping track of the registered styles */ |
| 14 |
protected $serializedStyleToStyleIdMappingTable = []; |
| 15 |
|
| 16 |
/** @var array [STYLE_ID] => [STYLE] mapping table, keeping track of the registered styles */ |
| 17 |
protected $styleIdToStyleMappingTable = []; |
| 18 |
|
| 19 |
/** |
| 20 |
* @param \Box\Spout\Writer\Style\Style $defaultStyle |
| 21 |
*/ |
| 22 |
public function __construct($defaultStyle) |
| 23 |
{ |
| 24 |
// This ensures that the default style is the first one to be registered |
| 25 |
$this->registerStyle($defaultStyle); |
| 26 |
} |
| 27 |
|
| 28 |
/** |
| 29 |
* Registers the given style as a used style. |
| 30 |
* Duplicate styles won't be registered more than once. |
| 31 |
* |
| 32 |
* @param \Box\Spout\Writer\Style\Style $style The style to be registered |
| 33 |
* @return \Box\Spout\Writer\Style\Style The registered style, updated with an internal ID. |
| 34 |
*/ |
| 35 |
public function registerStyle($style) |
| 36 |
{ |
| 37 |
$serializedStyle = $style->serialize(); |
| 38 |
|
| 39 |
if (!$this->hasStyleAlreadyBeenRegistered($style)) { |
| 40 |
$nextStyleId = count($this->serializedStyleToStyleIdMappingTable); |
| 41 |
$style->setId($nextStyleId); |
| 42 |
|
| 43 |
$this->serializedStyleToStyleIdMappingTable[$serializedStyle] = $nextStyleId; |
| 44 |
$this->styleIdToStyleMappingTable[$nextStyleId] = $style; |
| 45 |
} |
| 46 |
|
| 47 |
return $this->getStyleFromSerializedStyle($serializedStyle); |
| 48 |
} |
| 49 |
|
| 50 |
/** |
| 51 |
* Returns whether the given style has already been registered. |
| 52 |
* |
| 53 |
* @param \Box\Spout\Writer\Style\Style $style |
| 54 |
* @return bool |
| 55 |
*/ |
| 56 |
protected function hasStyleAlreadyBeenRegistered($style) |
| 57 |
{ |
| 58 |
$serializedStyle = $style->serialize(); |
| 59 |
|
| 60 |
// Using isset here because it is way faster than array_key_exists... |
| 61 |
return isset($this->serializedStyleToStyleIdMappingTable[$serializedStyle]); |
| 62 |
} |
| 63 |
|
| 64 |
/** |
| 65 |
* Returns the registered style associated to the given serialization. |
| 66 |
* |
| 67 |
* @param string $serializedStyle The serialized style from which the actual style should be fetched from |
| 68 |
* @return \Box\Spout\Writer\Style\Style |
| 69 |
*/ |
| 70 |
protected function getStyleFromSerializedStyle($serializedStyle) |
| 71 |
{ |
| 72 |
$styleId = $this->serializedStyleToStyleIdMappingTable[$serializedStyle]; |
| 73 |
return $this->styleIdToStyleMappingTable[$styleId]; |
| 74 |
} |
| 75 |
|
| 76 |
/** |
| 77 |
* @return \Box\Spout\Writer\Style\Style[] List of registered styles |
| 78 |
*/ |
| 79 |
protected function getRegisteredStyles() |
| 80 |
{ |
| 81 |
return array_values($this->styleIdToStyleMappingTable); |
| 82 |
} |
| 83 |
|
| 84 |
/** |
| 85 |
* Returns the default style |
| 86 |
* |
| 87 |
* @return \Box\Spout\Writer\Style\Style Default style |
| 88 |
*/ |
| 89 |
protected function getDefaultStyle() |
| 90 |
{ |
| 91 |
// By construction, the default style has ID 0 |
| 92 |
return $this->styleIdToStyleMappingTable[0]; |
| 93 |
} |
| 94 |
|
| 95 |
/** |
| 96 |
* Apply additional styles if the given row needs it. |
| 97 |
* Typically, set "wrap text" if a cell contains a new line. |
| 98 |
* |
| 99 |
* @param \Box\Spout\Writer\Style\Style $style The original style |
| 100 |
* @param array $dataRow The row the style will be applied to |
| 101 |
* @return \Box\Spout\Writer\Style\Style The updated style |
| 102 |
*/ |
| 103 |
public function applyExtraStylesIfNeeded($style, $dataRow) |
| 104 |
{ |
| 105 |
$updatedStyle = $this->applyWrapTextIfCellContainsNewLine($style, $dataRow); |
| 106 |
return $updatedStyle; |
| 107 |
} |
| 108 |
|
| 109 |
/** |
| 110 |
* Set the "wrap text" option if a cell of the given row contains a new line. |
| 111 |
* |
| 112 |
* @NOTE: There is a bug on the Mac version of Excel (2011 and below) where new lines |
| 113 |
* are ignored even when the "wrap text" option is set. This only occurs with |
| 114 |
* inline strings (shared strings do work fine). |
| 115 |
* A workaround would be to encode "\n" as "_x000D_" but it does not work |
| 116 |
* on the Windows version of Excel... |
| 117 |
* |
| 118 |
* @param \Box\Spout\Writer\Style\Style $style The original style |
| 119 |
* @param array $dataRow The row the style will be applied to |
| 120 |
* @return \Box\Spout\Writer\Style\Style The eventually updated style |
| 121 |
*/ |
| 122 |
protected function applyWrapTextIfCellContainsNewLine($style, $dataRow) |
| 123 |
{ |
| 124 |
// if the "wrap text" option is already set, no-op |
| 125 |
if ($style->hasSetWrapText()) { |
| 126 |
return $style; |
| 127 |
} |
| 128 |
|
| 129 |
foreach ($dataRow as $cell) { |
| 130 |
if (is_string($cell) && strpos($cell, "\n") !== false) { |
| 131 |
$style->setShouldWrapText(); |
| 132 |
break; |
| 133 |
} |
| 134 |
} |
| 135 |
|
| 136 |
return $style; |
| 137 |
} |
| 138 |
} |
| 139 |
|