Refactory Writer Styles to match new code organization (#433)

Decomposed old StyleHelper into StyleManager, StyleRegistry and StyleMerger.
This commit is contained in:
Adrien Loison authored and GitHub committed 2017-05-30 13:05:18 +02:00
1 parent 238756ab6e
commit cc9a0b526b
34 files changed
+1005 -762

No files matched your search

@@ -4,16 +4,14 @@ namespace Box\Spout\Writer\XLSX\Creator;
use Box\Spout\Common\Escaper;
use Box\Spout\Common\Helper\StringHelper;
use Box\Spout\Writer\Common\Manager\OptionsManagerInterface;
use Box\Spout\Writer\Common\Entity\Options;
use Box\Spout\Writer\Common\Creator\EntityFactory;
use Box\Spout\Writer\Common\Creator\InternalFactoryInterface;
use Box\Spout\Writer\Common\Creator\WorkbookFactory;
use Box\Spout\Writer\Common\Creator\WorksheetFactory;
use Box\Spout\Writer\Common\Manager\StyleManager;
use Box\Spout\Writer\Common\Entity\Options;
use Box\Spout\Writer\Common\Manager\OptionsManagerInterface;
use Box\Spout\Writer\XLSX\Helper\FileSystemHelper;
use Box\Spout\Writer\XLSX\Helper\SharedStringsHelper;
use Box\Spout\Writer\XLSX\Helper\StyleHelper;
use Box\Spout\Writer\XLSX\Manager\Style\StyleManager;
use Box\Spout\Writer\XLSX\Manager\Style\StyleRegistry;
use Box\Spout\Writer\XLSX\Manager\WorkbookManager;
use Box\Spout\Writer\XLSX\Manager\WorksheetManager;
@@ -52,29 +50,48 @@ class InternalFactory implements InternalFactoryInterface
$xlFolder = $fileSystemHelper->getXlFolder();
$sharedStringsHelper = $this->createSharedStringsHelper($xlFolder);
$styleHelper = $this->createStyleHelper($optionsManager);
$styleManager = $this->createStyleManager($optionsManager);
$worksheetManager = $this->createWorksheetManager($optionsManager, $styleManager, $sharedStringsHelper);
$worksheetManager = $this->createWorksheetManager($optionsManager, $sharedStringsHelper, $styleHelper);
return new WorkbookManager($workbook, $optionsManager, $worksheetManager, $styleHelper, $fileSystemHelper, $this->entityFactory);
return new WorkbookManager($workbook, $optionsManager, $worksheetManager, $styleManager, $fileSystemHelper, $this->entityFactory);
}
/**
* @param OptionsManagerInterface $optionsManager
* @param StyleManager $styleManager
* @param SharedStringsHelper $sharedStringsHelper
* @param StyleHelper $styleHelper
* @return WorksheetManager
*/
private function createWorksheetManager(
OptionsManagerInterface $optionsManager,
SharedStringsHelper $sharedStringsHelper,
StyleHelper $styleHelper
StyleManager $styleManager,
SharedStringsHelper $sharedStringsHelper
)
{
$stringsEscaper = $this->createStringsEscaper();
$stringsHelper = $this->createStringHelper();
return new WorksheetManager($optionsManager, $sharedStringsHelper, $styleHelper, $stringsEscaper, $stringsHelper);
return new WorksheetManager($optionsManager, $styleManager, $sharedStringsHelper, $stringsEscaper, $stringsHelper);
}
/**
* @param OptionsManagerInterface $optionsManager
* @return StyleManager
*/
private function createStyleManager(OptionsManagerInterface $optionsManager)
{
$styleRegistry = $this->createStyleRegistry($optionsManager);
return new StyleManager($styleRegistry);
}
/**
* @param OptionsManagerInterface $optionsManager
* @return StyleRegistry
*/
private function createStyleRegistry(OptionsManagerInterface $optionsManager)
{
$defaultRowStyle = $optionsManager->getOption(Options::DEFAULT_ROW_STYLE);
return new StyleRegistry($defaultRowStyle);
}
/**
@@ -96,26 +113,6 @@ class InternalFactory implements InternalFactoryInterface
return new FileSystemHelper($tempFolder);
}
/**
* @param OptionsManagerInterface $optionsManager
* @return StyleHelper
*/
private function createStyleHelper(OptionsManagerInterface $optionsManager)
{
$defaultRowStyle = $optionsManager->getOption(Options::DEFAULT_ROW_STYLE);
$styleManager = $this->createStyleManager();
return new StyleHelper($defaultRowStyle, $styleManager);
}
/**
* @return StyleManager
*/
private function createStyleManager()
{
return new StyleManager();
}
/**
* @return Escaper\XLSX
*/
@@ -2,9 +2,10 @@
namespace Box\Spout\Writer\XLSX\Helper;
use Box\Spout\Writer\Common\Entity\Worksheet;
use Box\Spout\Writer\Common\Helper\FileSystemWithRootFolderHelperInterface;
use Box\Spout\Writer\Common\Helper\ZipHelper;
use Box\Spout\Writer\Common\Entity\Worksheet;
use Box\Spout\Writer\XLSX\Manager\Style\StyleManager;
/**
* Class FileSystemHelper
@@ -335,12 +336,12 @@ EOD;
/**
* Creates the "styles.xml" file under the "xl" folder
*
* @param StyleHelper $styleHelper
* @param StyleManager $styleManager
* @return FileSystemHelper
*/
public function createStylesFile($styleHelper)
public function createStylesFile($styleManager)
{
$stylesXmlFileContents = $styleHelper->getStylesXMLFileContent();
$stylesXmlFileContents = $styleManager->getStylesXMLFileContent();
$this->createFileWithContents($this->xlFolder, self::STYLES_XML_FILE_NAME, $stylesXmlFileContents);
return $this;
@@ -1,124 +1,21 @@
<?php
namespace Box\Spout\Writer\XLSX\Helper;
namespace Box\Spout\Writer\XLSX\Manager\Style;
use Box\Spout\Writer\Common\Helper\StyleHelperAbstract;
use Box\Spout\Writer\Common\Entity\Style\Color;
use Box\Spout\Writer\Common\Entity\Style\Style;
use Box\Spout\Writer\XLSX\Helper\BorderHelper;
/**
* Class StyleHelper
* This class provides helper functions to manage styles
* Class StyleManager
* Manages styles to be applied to a cell
*
* @package Box\Spout\Writer\XLSX\Helper
* @package Box\Spout\Writer\XLSX\Manager\Style
*/
class StyleHelper extends StyleHelperAbstract
class StyleManager extends \Box\Spout\Writer\Common\Manager\Style\StyleManager
{
/**
* @var array
*/
protected $registeredFills = [];
/**
* @var array [STYLE_ID] => [FILL_ID] maps a style to a fill declaration
*/
protected $styleIdToFillMappingTable = [];
/**
* Excel preserves two default fills with index 0 and 1
* Since Excel is the dominant vendor - we play along here
*
* @var int The fill index counter for custom fills.
*/
protected $fillIndex = 2;
/**
* @var array
*/
protected $registeredBorders = [];
/**
* @var array [STYLE_ID] => [BORDER_ID] maps a style to a border declaration
*/
protected $styleIdToBorderMappingTable = [];
/**
* XLSX specific operations on the registered styles
*
* @param \Box\Spout\Writer\Common\Entity\Style\Style $style
* @return \Box\Spout\Writer\Common\Entity\Style\Style
*/
public function registerStyle($style)
{
$registeredStyle = parent::registerStyle($style);
$this->registerFill($registeredStyle);
$this->registerBorder($registeredStyle);
return $registeredStyle;
}
/**
* Register a fill definition
*
* @param \Box\Spout\Writer\Common\Entity\Style\Style $style
*/
protected function registerFill($style)
{
$styleId = $style->getId();
// Currently - only solid backgrounds are supported
// so $backgroundColor is a scalar value (RGB Color)
$backgroundColor = $style->getBackgroundColor();
if ($backgroundColor) {
$isBackgroundColorRegistered = isset($this->registeredFills[$backgroundColor]);
// We need to track the already registered background definitions
if ($isBackgroundColorRegistered) {
$registeredStyleId = $this->registeredFills[$backgroundColor];
$registeredFillId = $this->styleIdToFillMappingTable[$registeredStyleId];
$this->styleIdToFillMappingTable[$styleId] = $registeredFillId;
} else {
$this->registeredFills[$backgroundColor] = $styleId;
$this->styleIdToFillMappingTable[$styleId] = $this->fillIndex++;
}
} else {
// The fillId maps a style to a fill declaration
// When there is no background color definition - we default to 0
$this->styleIdToFillMappingTable[$styleId] = 0;
}
}
/**
* Register a border definition
*
* @param \Box\Spout\Writer\Common\Entity\Style\Style $style
*/
protected function registerBorder($style)
{
$styleId = $style->getId();
if ($style->shouldApplyBorder()) {
$border = $style->getBorder();
$serializedBorder = serialize($border);
$isBorderAlreadyRegistered = isset($this->registeredBorders[$serializedBorder]);
if ($isBorderAlreadyRegistered) {
$registeredStyleId = $this->registeredBorders[$serializedBorder];
$registeredBorderId = $this->styleIdToBorderMappingTable[$registeredStyleId];
$this->styleIdToBorderMappingTable[$styleId] = $registeredBorderId;
} else {
$this->registeredBorders[$serializedBorder] = $styleId;
$this->styleIdToBorderMappingTable[$styleId] = count($this->registeredBorders);
}
} else {
// If no border should be applied - the mapping is the default border: 0
$this->styleIdToBorderMappingTable[$styleId] = 0;
}
}
/** @var StyleRegistry */
protected $styleRegistry;
/**
* For empty cells, we can specify a style or not. If no style are specified,
@@ -132,8 +29,11 @@ class StyleHelper extends StyleHelperAbstract
*/
public function shouldApplyStyleOnEmptyCell($styleId)
{
$hasStyleCustomFill = (isset($this->styleIdToFillMappingTable[$styleId]) && $this->styleIdToFillMappingTable[$styleId] !== 0);
$hasStyleCustomBorders = (isset($this->styleIdToBorderMappingTable[$styleId]) && $this->styleIdToBorderMappingTable[$styleId] !== 0);
$associatedFillId = $this->styleRegistry->getFillIdForStyleId($styleId);
$hasStyleCustomFill = ($associatedFillId !== null && $associatedFillId !== 0);
$associatedBorderId = $this->styleRegistry->getBorderIdForStyleId($styleId);
$hasStyleCustomBorders = ($associatedBorderId !== null && $associatedBorderId !== 0);
return ($hasStyleCustomFill || $hasStyleCustomBorders);
}
@@ -172,10 +72,12 @@ EOD;
*/
protected function getFontsSectionContent()
{
$content = '<fonts count="' . count($this->styleIdToStyleMappingTable) . '">';
$registeredStyles = $this->styleRegistry->getRegisteredStyles();
/** @var \Box\Spout\Writer\Common\Entity\Style\Style $style */
foreach ($this->getRegisteredStyles() as $style) {
$content = '<fonts count="' . count($registeredStyles) . '">';
/** @var Style $style */
foreach ($registeredStyles as $style) {
$content .= '<font>';
$content .= '<sz val="' . $style->getFontSize() . '"/>';
@@ -210,17 +112,19 @@ EOD;
*/
protected function getFillsSectionContent()
{
$registeredFills = $this->styleRegistry->getRegisteredFills();
// Excel reserves two default fills
$fillsCount = count($this->registeredFills) + 2;
$fillsCount = count($registeredFills) + 2;
$content = sprintf('<fills count="%d">', $fillsCount);
$content .= '<fill><patternFill patternType="none"/></fill>';
$content .= '<fill><patternFill patternType="gray125"/></fill>';
// The other fills are actually registered by setting a background color
foreach ($this->registeredFills as $styleId) {
foreach ($registeredFills as $styleId) {
/** @var Style $style */
$style = $this->styleIdToStyleMappingTable[$styleId];
$style = $this->styleRegistry->getStyleFromStyleId($styleId);
$backgroundColor = $style->getBackgroundColor();
$content .= sprintf(
@@ -241,18 +145,19 @@ EOD;
*/
protected function getBordersSectionContent()
{
$registeredBorders = $this->styleRegistry->getRegisteredBorders();
// There is one default border with index 0
$borderCount = count($this->registeredBorders) + 1;
$borderCount = count($registeredBorders) + 1;
$content = '<borders count="' . $borderCount . '">';
// Default border starting at index 0
$content .= '<border><left/><right/><top/><bottom/></border>';
foreach ($this->registeredBorders as $styleId) {
foreach ($registeredBorders as $styleId) {
/** @var \Box\Spout\Writer\Common\Entity\Style\Style $style */
$style = $this->styleIdToStyleMappingTable[$styleId];
$style = $this->styleRegistry->getStyleFromStyleId($styleId);
$border = $style->getBorder();
$content .= '<border>';
@@ -265,7 +170,6 @@ EOD;
$part = $border->getPart($partName);
$content .= BorderHelper::serializeBorderPart($part);
}
}
$content .= '</border>';
@@ -297,14 +201,14 @@ EOD;
*/
protected function getCellXfsSectionContent()
{
$registeredStyles = $this->getRegisteredStyles();
$registeredStyles = $this->styleRegistry->getRegisteredStyles();
$content = '<cellXfs count="' . count($registeredStyles) . '">';
foreach ($registeredStyles as $style) {
$styleId = $style->getId();
$fillId = $this->styleIdToFillMappingTable[$styleId];
$borderId = $this->styleIdToBorderMappingTable[$styleId];
$fillId = $this->styleRegistry->getFillIdForStyleId($styleId);
$borderId = $this->styleRegistry->getBorderIdForStyleId($styleId);
$content .= '<xf numFmtId="0" fontId="' . $styleId . '" fillId="' . $fillId . '" borderId="' . $borderId . '" xfId="0"';
@@ -0,0 +1,158 @@
<?php
namespace Box\Spout\Writer\XLSX\Manager\Style;
use Box\Spout\Writer\Common\Entity\Style\Style;
/**
* Class StyleRegistry
* Registry for all used styles
*
* @package Box\Spout\Writer\XLSX\Manager\Style
*/
class StyleRegistry extends \Box\Spout\Writer\Common\Manager\Style\StyleRegistry
{
/**
* @var array
*/
protected $registeredFills = [];
/**
* @var array [STYLE_ID] => [FILL_ID] maps a style to a fill declaration
*/
protected $styleIdToFillMappingTable = [];
/**
* Excel preserves two default fills with index 0 and 1
* Since Excel is the dominant vendor - we play along here
*
* @var int The fill index counter for custom fills.
*/
protected $fillIndex = 2;
/**
* @var array
*/
protected $registeredBorders = [];
/**
* @var array [STYLE_ID] => [BORDER_ID] maps a style to a border declaration
*/
protected $styleIdToBorderMappingTable = [];
/**
* XLSX specific operations on the registered styles
*
* @param Style $style
* @return Style
*/
public function registerStyle(Style $style)
{
$registeredStyle = parent::registerStyle($style);
$this->registerFill($registeredStyle);
$this->registerBorder($registeredStyle);
return $registeredStyle;
}
/**
* Register a fill definition
*
* @param Style $style
*/
private function registerFill(Style $style)
{
$styleId = $style->getId();
// Currently - only solid backgrounds are supported
// so $backgroundColor is a scalar value (RGB Color)
$backgroundColor = $style->getBackgroundColor();
if ($backgroundColor) {
$isBackgroundColorRegistered = isset($this->registeredFills[$backgroundColor]);
// We need to track the already registered background definitions
if ($isBackgroundColorRegistered) {
$registeredStyleId = $this->registeredFills[$backgroundColor];
$registeredFillId = $this->styleIdToFillMappingTable[$registeredStyleId];
$this->styleIdToFillMappingTable[$styleId] = $registeredFillId;
} else {
$this->registeredFills[$backgroundColor] = $styleId;
$this->styleIdToFillMappingTable[$styleId] = $this->fillIndex++;
}
} else {
// The fillId maps a style to a fill declaration
// When there is no background color definition - we default to 0
$this->styleIdToFillMappingTable[$styleId] = 0;
}
}
/**
* @param int $styleId
* @return int|null Fill ID associated to the given style ID
*/
public function getFillIdForStyleId($styleId)
{
return (isset($this->styleIdToFillMappingTable[$styleId])) ?
$this->styleIdToFillMappingTable[$styleId] :
null;
}
/**
* Register a border definition
*
* @param Style $style
*/
private function registerBorder(Style $style)
{
$styleId = $style->getId();
if ($style->shouldApplyBorder()) {
$border = $style->getBorder();
$serializedBorder = serialize($border);
$isBorderAlreadyRegistered = isset($this->registeredBorders[$serializedBorder]);
if ($isBorderAlreadyRegistered) {
$registeredStyleId = $this->registeredBorders[$serializedBorder];
$registeredBorderId = $this->styleIdToBorderMappingTable[$registeredStyleId];
$this->styleIdToBorderMappingTable[$styleId] = $registeredBorderId;
} else {
$this->registeredBorders[$serializedBorder] = $styleId;
$this->styleIdToBorderMappingTable[$styleId] = count($this->registeredBorders);
}
} else {
// If no border should be applied - the mapping is the default border: 0
$this->styleIdToBorderMappingTable[$styleId] = 0;
}
}
/**
* @param int $styleId
* @return int|null Fill ID associated to the given style ID
*/
public function getBorderIdForStyleId($styleId)
{
return (isset($this->styleIdToBorderMappingTable[$styleId])) ?
$this->styleIdToBorderMappingTable[$styleId] :
null;
}
/**
* @return array
*/
public function getRegisteredFills()
{
return $this->registeredFills;
}
/**
* @return array
*/
public function getRegisteredBorders()
{
return $this->registeredBorders;
}
}
@@ -5,7 +5,7 @@ namespace Box\Spout\Writer\XLSX\Manager;
use Box\Spout\Writer\Common\Sheet;
use Box\Spout\Writer\Common\Manager\WorkbookManagerAbstract;
use Box\Spout\Writer\XLSX\Helper\FileSystemHelper;
use Box\Spout\Writer\XLSX\Helper\StyleHelper;
use Box\Spout\Writer\XLSX\Manager\Style\StyleManager;
/**
* Class WorkbookManager
@@ -24,12 +24,12 @@ class WorkbookManager extends WorkbookManagerAbstract
/** @var WorksheetManager Object used to manage worksheets */
protected $worksheetManager;
/** @var StyleManager Manages styles */
protected $styleManager;
/** @var FileSystemHelper Helper to perform file system operations */
protected $fileSystemHelper;
/** @var StyleHelper Helper to apply styles */
protected $styleHelper;
/**
* @return int Maximum number of rows/columns a sheet can contain
*/
@@ -72,7 +72,7 @@ class WorkbookManager extends WorkbookManagerAbstract
->createContentTypesFile($worksheets)
->createWorkbookFile($worksheets)
->createWorkbookRelsFile($worksheets)
->createStylesFile($this->styleHelper)
->createStylesFile($this->styleManager)
->zipRootFolderAndCopyToStream($finalFilePointer);
}
}
@@ -13,7 +13,7 @@ use Box\Spout\Writer\Common\Entity\Worksheet;
use Box\Spout\Writer\Common\Manager\WorksheetManagerInterface;
use Box\Spout\Writer\Common\Entity\Style\Style;
use Box\Spout\Writer\XLSX\Helper\SharedStringsHelper;
use Box\Spout\Writer\XLSX\Helper\StyleHelper;
use Box\Spout\Writer\XLSX\Manager\Style\StyleManager;
/**
* Class WorksheetManager
@@ -39,12 +39,12 @@ EOD;
/** @var bool Whether inline or shared strings should be used */
protected $shouldUseInlineStrings;
/** @var StyleManager Manages styles */
private $styleManager;
/** @var SharedStringsHelper Helper to write shared strings */
private $sharedStringsHelper;
/** @var StyleHelper Helper to work with styles */
private $styleHelper;
/** @var \Box\Spout\Common\Escaper\XLSX Strings escaper */
private $stringsEscaper;
@@ -55,21 +55,21 @@ EOD;
* WorksheetManager constructor.
*
* @param OptionsManagerInterface $optionsManager
* @param StyleManager $styleManager
* @param SharedStringsHelper $sharedStringsHelper
* @param StyleHelper $styleHelper
* @param \Box\Spout\Common\Escaper\XLSX $stringsEscaper
* @param StringHelper $stringHelper
*/
public function __construct(
OptionsManagerInterface $optionsManager,
StyleManager $styleManager,
SharedStringsHelper $sharedStringsHelper,
StyleHelper $styleHelper,
\Box\Spout\Common\Escaper\XLSX $stringsEscaper,
StringHelper $stringHelper)
{
$this->shouldUseInlineStrings = $optionsManager->getOption(Options::SHOULD_USE_INLINE_STRINGS);
$this->styleManager = $styleManager;
$this->sharedStringsHelper = $sharedStringsHelper;
$this->styleHelper = $styleHelper;
$this->stringsEscaper = $stringsEscaper;
$this->stringHelper = $stringHelper;
}
@@ -211,7 +211,7 @@ EOD;
} else if ($cell->isNumeric()) {
$cellXML .= '><v>' . $cell->getValue() . '</v></c>';
} else if ($cell->isEmpty()) {
if ($this->styleHelper->shouldApplyStyleOnEmptyCell($styleId)) {
if ($this->styleManager->shouldApplyStyleOnEmptyCell($styleId)) {
$cellXML .= '/>';
} else {
// don't write empty cells that do no need styling