Introduce an options manager for all writers (#423)

This will improve the management of options and simplify some methods' signatures.
This commit will also help moving the code to a better state regarding Dependency Injection.
This commit is contained in:
Adrien Loison 2017-05-24 13:17:50 +02:00 committed by GitHub
parent f9d8ad8be3
commit a366d0d0af
22 changed files with 447 additions and 113 deletions

View File

@ -2,6 +2,7 @@
namespace Box\Spout\Writer; namespace Box\Spout\Writer;
use Box\Spout\Writer\Common\Options;
use Box\Spout\Writer\Exception\WriterNotOpenedException; use Box\Spout\Writer\Exception\WriterNotOpenedException;
/** /**
@ -12,9 +13,6 @@ use Box\Spout\Writer\Exception\WriterNotOpenedException;
*/ */
abstract class AbstractMultiSheetsWriter extends AbstractWriter abstract class AbstractMultiSheetsWriter extends AbstractWriter
{ {
/** @var bool Whether new sheets should be automatically created when the max rows limit per sheet is reached */
protected $shouldCreateNewSheetsAutomatically = true;
/** /**
* @return Common\Internal\WorkbookInterface The workbook representing the file to be written * @return Common\Internal\WorkbookInterface The workbook representing the file to be written
*/ */
@ -33,7 +31,7 @@ abstract class AbstractMultiSheetsWriter extends AbstractWriter
{ {
$this->throwIfWriterAlreadyOpened('Writer must be configured before opening it.'); $this->throwIfWriterAlreadyOpened('Writer must be configured before opening it.');
$this->shouldCreateNewSheetsAutomatically = $shouldCreateNewSheetsAutomatically; $this->optionsManager->setOption(Options::SHOULD_CREATE_NEW_SHEETS_AUTOMATICALLY, $shouldCreateNewSheetsAutomatically);
return $this; return $this;
} }

View File

@ -6,9 +6,10 @@ use Box\Spout\Common\Exception\IOException;
use Box\Spout\Common\Exception\InvalidArgumentException; use Box\Spout\Common\Exception\InvalidArgumentException;
use Box\Spout\Common\Exception\SpoutException; use Box\Spout\Common\Exception\SpoutException;
use Box\Spout\Common\Helper\FileSystemHelper; use Box\Spout\Common\Helper\FileSystemHelper;
use Box\Spout\Writer\Common\Manager\OptionsManagerInterface;
use Box\Spout\Writer\Common\Options;
use Box\Spout\Writer\Exception\WriterAlreadyOpenedException; use Box\Spout\Writer\Exception\WriterAlreadyOpenedException;
use Box\Spout\Writer\Exception\WriterNotOpenedException; use Box\Spout\Writer\Exception\WriterNotOpenedException;
use Box\Spout\Writer\Style\StyleBuilder;
/** /**
* Class AbstractWriter * Class AbstractWriter
@ -30,12 +31,12 @@ abstract class AbstractWriter implements WriterInterface
/** @var \Box\Spout\Common\Helper\GlobalFunctionsHelper Helper to work with global functions */ /** @var \Box\Spout\Common\Helper\GlobalFunctionsHelper Helper to work with global functions */
protected $globalFunctionsHelper; protected $globalFunctionsHelper;
/** @var \Box\Spout\Writer\Common\Manager\OptionsManagerInterface Writer options manager */
protected $optionsManager;
/** @var Style\Style Style to be applied to the next written row(s) */ /** @var Style\Style Style to be applied to the next written row(s) */
protected $rowStyle; protected $rowStyle;
/** @var Style\Style Default row style. Each writer can have its own default style */
protected $defaultRowStyle;
/** @var string Content-Type value for the header - to be defined by child class */ /** @var string Content-Type value for the header - to be defined by child class */
protected static $headerContentType; protected static $headerContentType;
@ -65,11 +66,11 @@ abstract class AbstractWriter implements WriterInterface
abstract protected function closeWriter(); abstract protected function closeWriter();
/** /**
* * @param \Box\Spout\Writer\Common\Manager\OptionsManagerInterface $optionsManager
*/ */
public function __construct() public function __construct(OptionsManagerInterface $optionsManager)
{ {
$this->defaultRowStyle = $this->getDefaultRowStyle(); $this->optionsManager = $optionsManager;
$this->resetRowStyleToDefault(); $this->resetRowStyleToDefault();
} }
@ -83,7 +84,7 @@ abstract class AbstractWriter implements WriterInterface
*/ */
public function setDefaultRowStyle($defaultStyle) public function setDefaultRowStyle($defaultStyle)
{ {
$this->defaultRowStyle = $defaultStyle; $this->optionsManager->setOption(Options::DEFAULT_ROW_STYLE, $defaultStyle);
$this->resetRowStyleToDefault(); $this->resetRowStyleToDefault();
return $this; return $this;
} }
@ -307,17 +308,6 @@ abstract class AbstractWriter implements WriterInterface
return $this; return $this;
} }
/**
* Returns the default style to be applied to rows.
* Can be overriden by children to have a custom style.
*
* @return Style\Style
*/
protected function getDefaultRowStyle()
{
return (new StyleBuilder())->build();
}
/** /**
* Sets the style to be applied to the next written rows * Sets the style to be applied to the next written rows
* until it is changed or reset. * until it is changed or reset.
@ -328,7 +318,8 @@ abstract class AbstractWriter implements WriterInterface
private function setRowStyle($style) private function setRowStyle($style)
{ {
// Merge given style with the default one to inherit custom properties // Merge given style with the default one to inherit custom properties
$this->rowStyle = $style->mergeWith($this->defaultRowStyle); $defaultRowStyle = $this->optionsManager->getOption(Options::DEFAULT_ROW_STYLE);
$this->rowStyle = $style->mergeWith($defaultRowStyle);
} }
/** /**
@ -338,7 +329,7 @@ abstract class AbstractWriter implements WriterInterface
*/ */
private function resetRowStyleToDefault() private function resetRowStyleToDefault()
{ {
$this->rowStyle = $this->defaultRowStyle; $this->rowStyle = $this->optionsManager->getOption(Options::DEFAULT_ROW_STYLE);
} }
/** /**

View File

@ -0,0 +1,36 @@
<?php
namespace Box\Spout\Writer\CSV\Manager;
use Box\Spout\Writer\Common\Options;
/**
* Class OptionsManager
* CSV Writer options manager
*
* @package Box\Spout\Writer\CSV\Manager
*/
class OptionsManager extends \Box\Spout\Writer\Common\Manager\OptionsManager
{
/**
* @inheritdoc
*/
protected function getSupportedOptions()
{
return [
Options::FIELD_DELIMITER,
Options::FIELD_ENCLOSURE,
Options::SHOULD_ADD_BOM,
];
}
/**
* @inheritdoc
*/
protected function setDefaultOptions()
{
$this->setOption(Options::FIELD_DELIMITER, ',');
$this->setOption(Options::FIELD_ENCLOSURE, '"');
$this->setOption(Options::SHOULD_ADD_BOM, true);
}
}

View File

@ -5,6 +5,7 @@ namespace Box\Spout\Writer\CSV;
use Box\Spout\Writer\AbstractWriter; use Box\Spout\Writer\AbstractWriter;
use Box\Spout\Common\Exception\IOException; use Box\Spout\Common\Exception\IOException;
use Box\Spout\Common\Helper\EncodingHelper; use Box\Spout\Common\Helper\EncodingHelper;
use Box\Spout\Writer\Common\Options;
/** /**
* Class Writer * Class Writer
@ -20,18 +21,9 @@ class Writer extends AbstractWriter
/** @var string Content-Type value for the header */ /** @var string Content-Type value for the header */
protected static $headerContentType = 'text/csv; charset=UTF-8'; protected static $headerContentType = 'text/csv; charset=UTF-8';
/** @var string Defines the character used to delimit fields (one character only) */
protected $fieldDelimiter = ',';
/** @var string Defines the character used to enclose fields (one character only) */
protected $fieldEnclosure = '"';
/** @var int */ /** @var int */
protected $lastWrittenRowIndex = 0; protected $lastWrittenRowIndex = 0;
/** @var bool */
protected $shouldAddBOM = true;
/** /**
* Sets the field delimiter for the CSV * Sets the field delimiter for the CSV
* *
@ -41,7 +33,7 @@ class Writer extends AbstractWriter
*/ */
public function setFieldDelimiter($fieldDelimiter) public function setFieldDelimiter($fieldDelimiter)
{ {
$this->fieldDelimiter = $fieldDelimiter; $this->optionsManager->setOption(Options::FIELD_DELIMITER, $fieldDelimiter);
return $this; return $this;
} }
@ -54,19 +46,20 @@ class Writer extends AbstractWriter
*/ */
public function setFieldEnclosure($fieldEnclosure) public function setFieldEnclosure($fieldEnclosure)
{ {
$this->fieldEnclosure = $fieldEnclosure; $this->optionsManager->setOption(Options::FIELD_ENCLOSURE, $fieldEnclosure);
return $this; return $this;
} }
/** /**
* Set if a BOM has to be added to the file * Set if a BOM has to be added to the file
* *
* @api
* @param bool $shouldAddBOM * @param bool $shouldAddBOM
* @return Writer * @return Writer
*/ */
public function setShouldAddBOM($shouldAddBOM) public function setShouldAddBOM($shouldAddBOM)
{ {
$this->shouldAddBOM = (bool) $shouldAddBOM; $this->optionsManager->setOption(Options::SHOULD_ADD_BOM, (bool) $shouldAddBOM);
return $this; return $this;
} }
@ -77,7 +70,7 @@ class Writer extends AbstractWriter
*/ */
protected function openWriter() protected function openWriter()
{ {
if ($this->shouldAddBOM) { if ($this->optionsManager->getOption(Options::SHOULD_ADD_BOM)) {
// Adds UTF-8 BOM for Unicode compatibility // Adds UTF-8 BOM for Unicode compatibility
$this->globalFunctionsHelper->fputs($this->filePointer, EncodingHelper::BOM_UTF8); $this->globalFunctionsHelper->fputs($this->filePointer, EncodingHelper::BOM_UTF8);
} }
@ -94,7 +87,10 @@ class Writer extends AbstractWriter
*/ */
protected function addRowToWriter(array $dataRow, $style) protected function addRowToWriter(array $dataRow, $style)
{ {
$wasWriteSuccessful = $this->globalFunctionsHelper->fputcsv($this->filePointer, $dataRow, $this->fieldDelimiter, $this->fieldEnclosure); $fieldDelimiter = $this->optionsManager->getOption(Options::FIELD_DELIMITER);
$fieldEnclosure = $this->optionsManager->getOption(Options::FIELD_ENCLOSURE);
$wasWriteSuccessful = $this->globalFunctionsHelper->fputcsv($this->filePointer, $dataRow, $fieldDelimiter, $fieldEnclosure);
if ($wasWriteSuccessful === false) { if ($wasWriteSuccessful === false) {
throw new IOException('Unable to write data'); throw new IOException('Unable to write data');
} }

View File

@ -64,7 +64,7 @@ class Cell
} }
/** /**
* @param $value mixed * @param $value mixed|null
*/ */
public function setValue($value) public function setValue($value)
{ {
@ -90,6 +90,7 @@ class Cell
/** /**
* Get the current value type * Get the current value type
* @param mixed|null $value
* @return int * @return int
*/ */
protected function detectType($value) protected function detectType($value)

View File

@ -2,6 +2,8 @@
namespace Box\Spout\Writer\Common\Internal; namespace Box\Spout\Writer\Common\Internal;
use Box\Spout\Writer\Common\Manager\OptionsManagerInterface;
use Box\Spout\Writer\Common\Options;
use Box\Spout\Writer\Exception\SheetNotFoundException; use Box\Spout\Writer\Exception\SheetNotFoundException;
/** /**
@ -13,8 +15,8 @@ use Box\Spout\Writer\Exception\SheetNotFoundException;
*/ */
abstract class AbstractWorkbook implements WorkbookInterface abstract class AbstractWorkbook implements WorkbookInterface
{ {
/** @var bool Whether new sheets should be automatically created when the max rows limit per sheet is reached */ /** @var \Box\Spout\Writer\Common\Manager\OptionsManagerInterface $optionsManager */
protected $shouldCreateNewSheetsAutomatically; protected $optionManager;
/** @var string Timestamp based unique ID identifying the workbook */ /** @var string Timestamp based unique ID identifying the workbook */
protected $internalId; protected $internalId;
@ -26,13 +28,12 @@ abstract class AbstractWorkbook implements WorkbookInterface
protected $currentWorksheet; protected $currentWorksheet;
/** /**
* @param bool $shouldCreateNewSheetsAutomatically * @param \Box\Spout\Writer\Common\Manager\OptionsManagerInterface $optionsManager
* @param \Box\Spout\Writer\Style\Style $defaultRowStyle
* @throws \Box\Spout\Common\Exception\IOException If unable to create at least one of the base folders * @throws \Box\Spout\Common\Exception\IOException If unable to create at least one of the base folders
*/ */
public function __construct($shouldCreateNewSheetsAutomatically, $defaultRowStyle) public function __construct(OptionsManagerInterface $optionsManager)
{ {
$this->shouldCreateNewSheetsAutomatically = $shouldCreateNewSheetsAutomatically; $this->optionManager = $optionsManager;
$this->internalId = uniqid(); $this->internalId = uniqid();
} }
@ -155,7 +156,7 @@ abstract class AbstractWorkbook implements WorkbookInterface
// if we reached the maximum number of rows for the current sheet... // if we reached the maximum number of rows for the current sheet...
if ($hasReachedMaxRows) { if ($hasReachedMaxRows) {
// ... continue writing in a new sheet if option set // ... continue writing in a new sheet if option set
if ($this->shouldCreateNewSheetsAutomatically) { if ($this->optionManager->getOption(Options::SHOULD_CREATE_NEW_SHEETS_AUTOMATICALLY)) {
$currentWorksheet = $this->addNewSheetAndMakeItCurrent(); $currentWorksheet = $this->addNewSheetAndMakeItCurrent();
$updatedStyle = $styleHelper->applyExtraStylesIfNeeded($style, $dataRow); $updatedStyle = $styleHelper->applyExtraStylesIfNeeded($style, $dataRow);

View File

@ -0,0 +1,71 @@
<?php
namespace Box\Spout\Writer\Common\Manager;
/**
* Class OptionsManager
* Writer' options manager
*
* @package Box\Spout\Writer\Common\Manager
*/
abstract class OptionsManager implements OptionsManagerInterface
{
const PREFIX_OPTION = 'OPTION_';
/** @var string[] List of all supported option names */
private $supportedOptions = [];
/** @var array Associative array [OPTION_NAME => OPTION_VALUE] */
private $options = [];
/**
* WriterOptions constructor.
*/
public function __construct()
{
$this->supportedOptions = $this->getSupportedOptions();
$this->setDefaultOptions();
}
/**
* @return array List of supported options
*/
abstract protected function getSupportedOptions();
/**
* Sets the default options.
* To be overriden by child classes
*
* @return void
*/
abstract protected function setDefaultOptions();
/**
* Sets the given option, if this option is supported.
*
* @param string $optionName
* @param mixed $optionValue
* @return void
*/
public function setOption($optionName, $optionValue)
{
if (in_array($optionName, $this->supportedOptions)) {
$this->options[$optionName] = $optionValue;
}
}
/**
* @param string $optionName
* @return mixed|null The set option or NULL if no option with given name found
*/
public function getOption($optionName)
{
$optionValue = null;
if (isset($this->options[$optionName])) {
$optionValue = $this->options[$optionName];
}
return $optionValue;
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace Box\Spout\Writer\Common\Manager;
/**
* Interface OptionsManagerInterface
* Writer' options interface
*
* @package Box\Spout\Writer\Common\Manager
*/
interface OptionsManagerInterface
{
/**
* @param string $optionName
* @param mixed $optionValue
* @return void
*/
public function setOption($optionName, $optionValue);
/**
* @param string $optionName
* @return mixed|null The set option or NULL if no option with given name found
*/
public function getOption($optionName);
}

View File

@ -0,0 +1,25 @@
<?php
namespace Box\Spout\Writer\Common;
/**
* Class Options
* Writer' options holder
*
* @package Box\Spout\Writer\Common
*/
abstract class Options
{
// CSV specific options
const FIELD_DELIMITER = 'fieldDelimiter';
const FIELD_ENCLOSURE = 'fieldEnclosure';
const SHOULD_ADD_BOM = 'shouldAddBOM';
// Multisheets options
const TEMP_FOLDER = 'tempFolder';
const DEFAULT_ROW_STYLE = 'defaultRowStyle';
const SHOULD_CREATE_NEW_SHEETS_AUTOMATICALLY = 'shouldCreateNewSheetsAutomatically';
// XLSX specific options
const SHOULD_USE_INLINE_STRINGS = 'shouldUseInlineStrings';
}

View File

@ -3,6 +3,8 @@
namespace Box\Spout\Writer\ODS\Internal; namespace Box\Spout\Writer\ODS\Internal;
use Box\Spout\Writer\Common\Internal\AbstractWorkbook; use Box\Spout\Writer\Common\Internal\AbstractWorkbook;
use Box\Spout\Writer\Common\Manager\OptionsManagerInterface;
use Box\Spout\Writer\Common\Options;
use Box\Spout\Writer\ODS\Helper\FileSystemHelper; use Box\Spout\Writer\ODS\Helper\FileSystemHelper;
use Box\Spout\Writer\ODS\Helper\StyleHelper; use Box\Spout\Writer\ODS\Helper\StyleHelper;
use Box\Spout\Writer\Common\Sheet; use Box\Spout\Writer\Common\Sheet;
@ -29,18 +31,18 @@ class Workbook extends AbstractWorkbook
protected $styleHelper; protected $styleHelper;
/** /**
* @param string $tempFolder * @param \Box\Spout\Writer\Common\Manager\OptionsManagerInterface $optionsManager Options manager
* @param bool $shouldCreateNewSheetsAutomatically
* @param \Box\Spout\Writer\Style\Style $defaultRowStyle
* @throws \Box\Spout\Common\Exception\IOException If unable to create at least one of the base folders * @throws \Box\Spout\Common\Exception\IOException If unable to create at least one of the base folders
*/ */
public function __construct($tempFolder, $shouldCreateNewSheetsAutomatically, $defaultRowStyle) public function __construct(OptionsManagerInterface $optionsManager)
{ {
parent::__construct($shouldCreateNewSheetsAutomatically, $defaultRowStyle); parent::__construct($optionsManager);
$tempFolder = $optionsManager->getOption(Options::TEMP_FOLDER);
$this->fileSystemHelper = new FileSystemHelper($tempFolder); $this->fileSystemHelper = new FileSystemHelper($tempFolder);
$this->fileSystemHelper->createBaseFilesAndFolders(); $this->fileSystemHelper->createBaseFilesAndFolders();
$defaultRowStyle = $optionsManager->getOption(Options::DEFAULT_ROW_STYLE);
$this->styleHelper = new StyleHelper($defaultRowStyle); $this->styleHelper = new StyleHelper($defaultRowStyle);
} }

View File

@ -0,0 +1,50 @@
<?php
namespace Box\Spout\Writer\ODS\Manager;
use Box\Spout\Writer\Common\Options;
use Box\Spout\Writer\Style\StyleBuilder;
/**
* Class OptionsManager
* ODS Writer options manager
*
* @package Box\Spout\Writer\ODS\Manager
*/
class OptionsManager extends \Box\Spout\Writer\Common\Manager\OptionsManager
{
/** @var StyleBuilder Style builder */
protected $styleBuilder;
/**
* OptionsManager constructor.
* @param StyleBuilder $styleBuilder
*/
public function __construct(StyleBuilder $styleBuilder)
{
$this->styleBuilder = $styleBuilder;
parent::__construct();
}
/**
* @inheritdoc
*/
protected function getSupportedOptions()
{
return [
Options::TEMP_FOLDER,
Options::DEFAULT_ROW_STYLE,
Options::SHOULD_CREATE_NEW_SHEETS_AUTOMATICALLY,
];
}
/**
* @inheritdoc
*/
protected function setDefaultOptions()
{
$this->setOption(Options::TEMP_FOLDER, sys_get_temp_dir());
$this->setOption(Options::DEFAULT_ROW_STYLE, $this->styleBuilder->build());
$this->setOption(Options::SHOULD_CREATE_NEW_SHEETS_AUTOMATICALLY, true);
}
}

View File

@ -4,6 +4,7 @@ namespace Box\Spout\Writer\ODS;
use Box\Spout\Writer\AbstractMultiSheetsWriter; use Box\Spout\Writer\AbstractMultiSheetsWriter;
use Box\Spout\Writer\Common; use Box\Spout\Writer\Common;
use Box\Spout\Writer\Common\Options;
use Box\Spout\Writer\ODS\Internal\Workbook; use Box\Spout\Writer\ODS\Internal\Workbook;
/** /**
@ -17,9 +18,6 @@ class Writer extends AbstractMultiSheetsWriter
/** @var string Content-Type value for the header */ /** @var string Content-Type value for the header */
protected static $headerContentType = 'application/vnd.oasis.opendocument.spreadsheet'; protected static $headerContentType = 'application/vnd.oasis.opendocument.spreadsheet';
/** @var string Temporary folder where the files to create the ODS will be stored */
protected $tempFolder;
/** @var Internal\Workbook The workbook for the ODS file */ /** @var Internal\Workbook The workbook for the ODS file */
protected $book; protected $book;
@ -36,7 +34,7 @@ class Writer extends AbstractMultiSheetsWriter
{ {
$this->throwIfWriterAlreadyOpened('Writer must be configured before opening it.'); $this->throwIfWriterAlreadyOpened('Writer must be configured before opening it.');
$this->tempFolder = $tempFolder; $this->optionsManager->setOption(Options::TEMP_FOLDER, $tempFolder);
return $this; return $this;
} }
@ -48,8 +46,7 @@ class Writer extends AbstractMultiSheetsWriter
*/ */
protected function openWriter() protected function openWriter()
{ {
$tempFolder = ($this->tempFolder) ? : sys_get_temp_dir(); $this->book = new Workbook($this->optionsManager);
$this->book = new Workbook($tempFolder, $this->shouldCreateNewSheetsAutomatically, $this->defaultRowStyle);
$this->book->addNewSheetAndMakeItCurrent(); $this->book->addNewSheetAndMakeItCurrent();
} }

View File

@ -61,14 +61,10 @@ class Style
/** @var bool Whether the wrap text property was set */ /** @var bool Whether the wrap text property was set */
protected $hasSetWrapText = false; protected $hasSetWrapText = false;
/** /** @var Border */
* @var Border
*/
protected $border = null; protected $border = null;
/** /** @var bool Whether border properties should be applied */
* @var bool Whether border properties should be applied
*/
protected $shouldApplyBorder = false; protected $shouldApplyBorder = false;
/** @var string Background color */ /** @var string Background color */

View File

@ -5,6 +5,7 @@ namespace Box\Spout\Writer;
use Box\Spout\Common\Exception\UnsupportedTypeException; use Box\Spout\Common\Exception\UnsupportedTypeException;
use Box\Spout\Common\Helper\GlobalFunctionsHelper; use Box\Spout\Common\Helper\GlobalFunctionsHelper;
use Box\Spout\Common\Type; use Box\Spout\Common\Type;
use Box\Spout\Writer\Style\StyleBuilder;
/** /**
* Class WriterFactory * Class WriterFactory
@ -29,13 +30,13 @@ class WriterFactory
switch ($writerType) { switch ($writerType) {
case Type::CSV: case Type::CSV:
$writer = new CSV\Writer(); $writer = self::getCSVWriter();
break; break;
case Type::XLSX: case Type::XLSX:
$writer = new XLSX\Writer(); $writer = self::getXLSXWriter();
break; break;
case Type::ODS: case Type::ODS:
$writer = new ODS\Writer(); $writer = self::getODSWriter();
break; break;
default: default:
throw new UnsupportedTypeException('No writers supporting the given type: ' . $writerType); throw new UnsupportedTypeException('No writers supporting the given type: ' . $writerType);
@ -45,4 +46,36 @@ class WriterFactory
return $writer; return $writer;
} }
/**
* @return CSV\Writer
*/
private static function getCSVWriter()
{
$optionsManager = new CSV\Manager\OptionsManager();
return new CSV\Writer($optionsManager);
}
/**
* @return XLSX\Writer
*/
private static function getXLSXWriter()
{
$styleBuilder = new StyleBuilder();
$optionsManager = new XLSX\Manager\OptionsManager($styleBuilder);
return new XLSX\Writer($optionsManager);
}
/**
* @return ODS\Writer
*/
private static function getODSWriter()
{
$styleBuilder = new StyleBuilder();
$optionsManager = new ODS\Manager\OptionsManager($styleBuilder);
return new ODS\Writer($optionsManager);
}
} }

View File

@ -3,10 +3,13 @@
namespace Box\Spout\Writer\XLSX\Internal; namespace Box\Spout\Writer\XLSX\Internal;
use Box\Spout\Writer\Common\Internal\AbstractWorkbook; use Box\Spout\Writer\Common\Internal\AbstractWorkbook;
use Box\Spout\Writer\Common\Manager\OptionsManagerInterface;
use Box\Spout\Writer\Common\Options;
use Box\Spout\Writer\XLSX\Helper\FileSystemHelper; use Box\Spout\Writer\XLSX\Helper\FileSystemHelper;
use Box\Spout\Writer\XLSX\Helper\SharedStringsHelper; use Box\Spout\Writer\XLSX\Helper\SharedStringsHelper;
use Box\Spout\Writer\XLSX\Helper\StyleHelper; use Box\Spout\Writer\XLSX\Helper\StyleHelper;
use Box\Spout\Writer\Common\Sheet; use Box\Spout\Writer\Common\Sheet;
use Box\Spout\Writer\XLSX\Manager\OptionsManager;
/** /**
* Class Workbook * Class Workbook
@ -36,21 +39,18 @@ class Workbook extends AbstractWorkbook
protected $styleHelper; protected $styleHelper;
/** /**
* @param string $tempFolder * @param \Box\Spout\Writer\Common\Manager\OptionsManagerInterface $optionsManager Options manager
* @param bool $shouldUseInlineStrings
* @param bool $shouldCreateNewSheetsAutomatically
* @param \Box\Spout\Writer\Style\Style $defaultRowStyle
* @throws \Box\Spout\Common\Exception\IOException If unable to create at least one of the base folders * @throws \Box\Spout\Common\Exception\IOException If unable to create at least one of the base folders
*/ */
public function __construct($tempFolder, $shouldUseInlineStrings, $shouldCreateNewSheetsAutomatically, $defaultRowStyle) public function __construct(OptionsManagerInterface $optionsManager)
{ {
parent::__construct($shouldCreateNewSheetsAutomatically, $defaultRowStyle); parent::__construct($optionsManager);
$this->shouldUseInlineStrings = $shouldUseInlineStrings;
$tempFolder = $optionsManager->getOption(Options::TEMP_FOLDER);
$this->fileSystemHelper = new FileSystemHelper($tempFolder); $this->fileSystemHelper = new FileSystemHelper($tempFolder);
$this->fileSystemHelper->createBaseFilesAndFolders(); $this->fileSystemHelper->createBaseFilesAndFolders();
$defaultRowStyle = $optionsManager->getOption(Options::DEFAULT_ROW_STYLE);
$this->styleHelper = new StyleHelper($defaultRowStyle); $this->styleHelper = new StyleHelper($defaultRowStyle);
// This helper will be shared by all sheets // This helper will be shared by all sheets
@ -86,7 +86,7 @@ class Workbook extends AbstractWorkbook
$sheet = new Sheet($newSheetIndex, $this->internalId); $sheet = new Sheet($newSheetIndex, $this->internalId);
$worksheetFilesFolder = $this->fileSystemHelper->getXlWorksheetsFolder(); $worksheetFilesFolder = $this->fileSystemHelper->getXlWorksheetsFolder();
$worksheet = new Worksheet($sheet, $worksheetFilesFolder, $this->sharedStringsHelper, $this->styleHelper, $this->shouldUseInlineStrings); $worksheet = new Worksheet($sheet, $worksheetFilesFolder, $this->sharedStringsHelper, $this->styleHelper, $this->optionManager);
$this->worksheets[] = $worksheet; $this->worksheets[] = $worksheet;
return $worksheet; return $worksheet;

View File

@ -8,6 +8,8 @@ use Box\Spout\Common\Helper\StringHelper;
use Box\Spout\Writer\Common\Cell; use Box\Spout\Writer\Common\Cell;
use Box\Spout\Writer\Common\Helper\CellHelper; use Box\Spout\Writer\Common\Helper\CellHelper;
use Box\Spout\Writer\Common\Internal\WorksheetInterface; use Box\Spout\Writer\Common\Internal\WorksheetInterface;
use Box\Spout\Writer\Common\Manager\OptionsManagerInterface;
use Box\Spout\Writer\Common\Options;
/** /**
* Class Worksheet * Class Worksheet
@ -62,16 +64,16 @@ EOD;
* @param \Box\Spout\Writer\Common\Sheet $externalSheet The associated "external" sheet * @param \Box\Spout\Writer\Common\Sheet $externalSheet The associated "external" sheet
* @param string $worksheetFilesFolder Temporary folder where the files to create the XLSX will be stored * @param string $worksheetFilesFolder Temporary folder where the files to create the XLSX will be stored
* @param \Box\Spout\Writer\XLSX\Helper\SharedStringsHelper $sharedStringsHelper Helper for shared strings * @param \Box\Spout\Writer\XLSX\Helper\SharedStringsHelper $sharedStringsHelper Helper for shared strings
* @param \Box\Spout\Writer\XLSX\Helper\StyleHelper Helper to work with styles * @param \Box\Spout\Writer\XLSX\Helper\StyleHelper $styleHelper Helper to work with styles
* @param bool $shouldUseInlineStrings Whether inline or shared strings should be used * @param \Box\Spout\Writer\Common\Manager\OptionsManagerInterface $optionsManager Options manager
* @throws \Box\Spout\Common\Exception\IOException If the sheet data file cannot be opened for writing * @throws \Box\Spout\Common\Exception\IOException If the sheet data file cannot be opened for writing
*/ */
public function __construct($externalSheet, $worksheetFilesFolder, $sharedStringsHelper, $styleHelper, $shouldUseInlineStrings) public function __construct($externalSheet, $worksheetFilesFolder, $sharedStringsHelper, $styleHelper, OptionsManagerInterface $optionsManager)
{ {
$this->externalSheet = $externalSheet; $this->externalSheet = $externalSheet;
$this->sharedStringsHelper = $sharedStringsHelper; $this->sharedStringsHelper = $sharedStringsHelper;
$this->styleHelper = $styleHelper; $this->styleHelper = $styleHelper;
$this->shouldUseInlineStrings = $shouldUseInlineStrings; $this->shouldUseInlineStrings = $optionsManager->getOption(Options::SHOULD_USE_INLINE_STRINGS);
/** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */ /** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */
$this->stringsEscaper = \Box\Spout\Common\Escaper\XLSX::getInstance(); $this->stringsEscaper = \Box\Spout\Common\Escaper\XLSX::getInstance();

View File

@ -0,0 +1,61 @@
<?php
namespace Box\Spout\Writer\XLSX\Manager;
use Box\Spout\Writer\Common\Options;
use Box\Spout\Writer\Style\StyleBuilder;
/**
* Class OptionsManager
* XLSX Writer options manager
*
* @package Box\Spout\Writer\XLSX\Manager
*/
class OptionsManager extends \Box\Spout\Writer\Common\Manager\OptionsManager
{
/** Default style font values */
const DEFAULT_FONT_SIZE = 12;
const DEFAULT_FONT_NAME = 'Calibri';
/** @var StyleBuilder Style builder */
protected $styleBuilder;
/**
* OptionsManager constructor.
* @param StyleBuilder $styleBuilder
*/
public function __construct(StyleBuilder $styleBuilder)
{
$this->styleBuilder = $styleBuilder;
parent::__construct();
}
/**
* @inheritdoc
*/
protected function getSupportedOptions()
{
return [
Options::TEMP_FOLDER,
Options::DEFAULT_ROW_STYLE,
Options::SHOULD_CREATE_NEW_SHEETS_AUTOMATICALLY,
Options::SHOULD_USE_INLINE_STRINGS,
];
}
/**
* @inheritdoc
*/
protected function setDefaultOptions()
{
$defaultRowStyle = $this->styleBuilder
->setFontSize(self::DEFAULT_FONT_SIZE)
->setFontName(self::DEFAULT_FONT_NAME)
->build();
$this->setOption(Options::TEMP_FOLDER, sys_get_temp_dir());
$this->setOption(Options::DEFAULT_ROW_STYLE, $defaultRowStyle);
$this->setOption(Options::SHOULD_CREATE_NEW_SHEETS_AUTOMATICALLY, true);
$this->setOption(Options::SHOULD_USE_INLINE_STRINGS, true);
}
}

View File

@ -3,6 +3,7 @@
namespace Box\Spout\Writer\XLSX; namespace Box\Spout\Writer\XLSX;
use Box\Spout\Writer\AbstractMultiSheetsWriter; use Box\Spout\Writer\AbstractMultiSheetsWriter;
use Box\Spout\Writer\Common\Options;
use Box\Spout\Writer\Style\StyleBuilder; use Box\Spout\Writer\Style\StyleBuilder;
use Box\Spout\Writer\XLSX\Internal\Workbook; use Box\Spout\Writer\XLSX\Internal\Workbook;
@ -14,19 +15,9 @@ use Box\Spout\Writer\XLSX\Internal\Workbook;
*/ */
class Writer extends AbstractMultiSheetsWriter class Writer extends AbstractMultiSheetsWriter
{ {
/** Default style font values */
const DEFAULT_FONT_SIZE = 12;
const DEFAULT_FONT_NAME = 'Calibri';
/** @var string Content-Type value for the header */ /** @var string Content-Type value for the header */
protected static $headerContentType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'; protected static $headerContentType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
/** @var string Temporary folder where the files to create the XLSX will be stored */
protected $tempFolder;
/** @var bool Whether inline or shared strings should be used - inline string is more memory efficient */
protected $shouldUseInlineStrings = true;
/** @var Internal\Workbook The workbook for the XLSX file */ /** @var Internal\Workbook The workbook for the XLSX file */
protected $book; protected $book;
@ -43,7 +34,7 @@ class Writer extends AbstractMultiSheetsWriter
{ {
$this->throwIfWriterAlreadyOpened('Writer must be configured before opening it.'); $this->throwIfWriterAlreadyOpened('Writer must be configured before opening it.');
$this->tempFolder = $tempFolder; $this->optionsManager->setOption(Options::TEMP_FOLDER, $tempFolder);
return $this; return $this;
} }
@ -60,7 +51,7 @@ class Writer extends AbstractMultiSheetsWriter
{ {
$this->throwIfWriterAlreadyOpened('Writer must be configured before opening it.'); $this->throwIfWriterAlreadyOpened('Writer must be configured before opening it.');
$this->shouldUseInlineStrings = $shouldUseInlineStrings; $this->optionsManager->setOption(Options::SHOULD_USE_INLINE_STRINGS, $shouldUseInlineStrings);
return $this; return $this;
} }
@ -73,8 +64,7 @@ class Writer extends AbstractMultiSheetsWriter
protected function openWriter() protected function openWriter()
{ {
if (!$this->book) { if (!$this->book) {
$tempFolder = ($this->tempFolder) ? : sys_get_temp_dir(); $this->book = new Workbook($this->optionsManager);
$this->book = new Workbook($tempFolder, $this->shouldUseInlineStrings, $this->shouldCreateNewSheetsAutomatically, $this->defaultRowStyle);
$this->book->addNewSheetAndMakeItCurrent(); $this->book->addNewSheetAndMakeItCurrent();
} }
} }
@ -105,19 +95,6 @@ class Writer extends AbstractMultiSheetsWriter
$this->book->addRowToCurrentWorksheet($dataRow, $style); $this->book->addRowToCurrentWorksheet($dataRow, $style);
} }
/**
* Returns the default style to be applied to rows.
*
* @return \Box\Spout\Writer\Style\Style
*/
protected function getDefaultRowStyle()
{
return (new StyleBuilder())
->setFontSize(self::DEFAULT_FONT_SIZE)
->setFontName(self::DEFAULT_FONT_NAME)
->build();
}
/** /**
* Closes the writer, preventing any additional writing. * Closes the writer, preventing any additional writing.
* *

View File

@ -204,6 +204,7 @@ class WriterTest extends \PHPUnit_Framework_TestCase
$this->createGeneratedFolderIfNeeded($fileName); $this->createGeneratedFolderIfNeeded($fileName);
$resourcePath = $this->getGeneratedResourcePath($fileName); $resourcePath = $this->getGeneratedResourcePath($fileName);
/** @var \Box\Spout\Writer\CSV\Writer $writer */
$writer = WriterFactory::create(Type::CSV); $writer = WriterFactory::create(Type::CSV);
$writer->setFieldDelimiter($fieldDelimiter); $writer->setFieldDelimiter($fieldDelimiter);
$writer->setFieldEnclosure($fieldEnclosure); $writer->setFieldEnclosure($fieldEnclosure);

View File

@ -0,0 +1,70 @@
<?php
namespace Box\Spout\Writer\Common\Manager;
/**
* Class OptionsManagerTest
*
* @package Box\Spout\Writer\Common\Manager
*/
class OptionsManagerTest extends \PHPUnit_Framework_TestCase
{
/**
* @return void
*/
public function testOptionsManagerShouldReturnDefaultOptionsIfNothingSet()
{
$optionsManager = new FakeOptionsManager();
$this->assertEquals('foo-val', $optionsManager->getOption('foo'));
$this->assertEquals(false, $optionsManager->getOption('bar'));
}
/**
* @return void
*/
public function testOptionsManagerShouldReturnUpdatedOptionValue()
{
$optionsManager = new FakeOptionsManager();
$optionsManager->setOption('foo', 'new-val');
$this->assertEquals('new-val', $optionsManager->getOption('foo'));
}
/**
* @return void
*/
public function testOptionsManagerShouldReturnNullIfNoDefaultValueSet()
{
$optionsManager = new FakeOptionsManager();
$this->assertNull($optionsManager->getOption('baz'));
}
/**
* @return void
*/
public function testOptionsManagerShouldReturnNullIfNoOptionNotSupported()
{
$optionsManager = new FakeOptionsManager();
$optionsManager->setOption('not-supported', 'something');
$this->assertNull($optionsManager->getOption('not-supported'));
}
}
// TODO: Convert this to anonymous class when PHP < 7 support is dropped
class FakeOptionsManager extends OptionsManager
{
protected function getSupportedOptions()
{
return [
'foo',
'bar',
'baz',
];
}
protected function setDefaultOptions()
{
$this->setOption('foo', 'foo-val');
$this->setOption('bar', false);
}
}

View File

@ -375,7 +375,7 @@ class WriterWithStyleTest extends \PHPUnit_Framework_TestCase
$this->createGeneratedFolderIfNeeded($fileName); $this->createGeneratedFolderIfNeeded($fileName);
$resourcePath = $this->getGeneratedResourcePath($fileName); $resourcePath = $this->getGeneratedResourcePath($fileName);
/** @var \Box\Spout\Writer\XLSX\Writer $writer */ /** @var \Box\Spout\Writer\ODS\Writer $writer */
$writer = WriterFactory::create(Type::ODS); $writer = WriterFactory::create(Type::ODS);
$writer->setDefaultRowStyle($defaultStyle); $writer->setDefaultRowStyle($defaultStyle);
@ -467,7 +467,7 @@ class WriterWithStyleTest extends \PHPUnit_Framework_TestCase
/** /**
* @param string $fileName * @param string $fileName
* @param string $section * @param string $section
* @return \DomElement * @return \DomNode
*/ */
private function getXmlSectionFromStylesXmlFile($fileName, $section) private function getXmlSectionFromStylesXmlFile($fileName, $section)
{ {

View File

@ -11,6 +11,7 @@ use Box\Spout\Writer\Style\Color;
use Box\Spout\Writer\Style\Style; use Box\Spout\Writer\Style\Style;
use Box\Spout\Writer\Style\StyleBuilder; use Box\Spout\Writer\Style\StyleBuilder;
use Box\Spout\Writer\WriterFactory; use Box\Spout\Writer\WriterFactory;
use Box\Spout\Writer\XLSX\Manager\OptionsManager;
/** /**
* Class WriterWithStyleTest * Class WriterWithStyleTest
@ -129,9 +130,9 @@ class WriterWithStyleTest extends \PHPUnit_Framework_TestCase
// First font should be the default one // First font should be the default one
$defaultFontElement = $fontElements->item(0); $defaultFontElement = $fontElements->item(0);
$this->assertChildrenNumEquals(3, $defaultFontElement, 'The default font should only have 3 properties.'); $this->assertChildrenNumEquals(3, $defaultFontElement, 'The default font should only have 3 properties.');
$this->assertFirstChildHasAttributeEquals((string) Writer::DEFAULT_FONT_SIZE, $defaultFontElement, 'sz', 'val'); $this->assertFirstChildHasAttributeEquals((string) OptionsManager::DEFAULT_FONT_SIZE, $defaultFontElement, 'sz', 'val');
$this->assertFirstChildHasAttributeEquals(Color::toARGB(Style::DEFAULT_FONT_COLOR), $defaultFontElement, 'color', 'rgb'); $this->assertFirstChildHasAttributeEquals(Color::toARGB(Style::DEFAULT_FONT_COLOR), $defaultFontElement, 'color', 'rgb');
$this->assertFirstChildHasAttributeEquals(Writer::DEFAULT_FONT_NAME, $defaultFontElement, 'name', 'val'); $this->assertFirstChildHasAttributeEquals(OptionsManager::DEFAULT_FONT_NAME, $defaultFontElement, 'name', 'val');
// Second font should contain data from the first created style // Second font should contain data from the first created style
$secondFontElement = $fontElements->item(1); $secondFontElement = $fontElements->item(1);
@ -140,9 +141,9 @@ class WriterWithStyleTest extends \PHPUnit_Framework_TestCase
$this->assertChildExists($secondFontElement, 'i'); $this->assertChildExists($secondFontElement, 'i');
$this->assertChildExists($secondFontElement, 'u'); $this->assertChildExists($secondFontElement, 'u');
$this->assertChildExists($secondFontElement, 'strike'); $this->assertChildExists($secondFontElement, 'strike');
$this->assertFirstChildHasAttributeEquals((string) Writer::DEFAULT_FONT_SIZE, $secondFontElement, 'sz', 'val'); $this->assertFirstChildHasAttributeEquals((string) OptionsManager::DEFAULT_FONT_SIZE, $secondFontElement, 'sz', 'val');
$this->assertFirstChildHasAttributeEquals(Color::toARGB(Style::DEFAULT_FONT_COLOR), $secondFontElement, 'color', 'rgb'); $this->assertFirstChildHasAttributeEquals(Color::toARGB(Style::DEFAULT_FONT_COLOR), $secondFontElement, 'color', 'rgb');
$this->assertFirstChildHasAttributeEquals(Writer::DEFAULT_FONT_NAME, $secondFontElement, 'name', 'val'); $this->assertFirstChildHasAttributeEquals(OptionsManager::DEFAULT_FONT_NAME, $secondFontElement, 'name', 'val');
// Third font should contain data from the second created style // Third font should contain data from the second created style
$thirdFontElement = $fontElements->item(2); $thirdFontElement = $fontElements->item(2);