Refactor readers to get a proper DI

Similar to what was done with writers, readers also needed to be updated to match the new way of doing things.
This commits promotes a better DI (factories, injection through constructors).
This commit is contained in:
Adrien Loison 2017-08-26 22:12:59 +02:00
parent 4d6437fa77
commit 1021dad230
53 changed files with 994 additions and 507 deletions

View File

@ -0,0 +1,42 @@
<?php
namespace Box\Spout\Common\Creator;
use Box\Spout\Common\Helper\EncodingHelper;
use Box\Spout\Common\Helper\FileSystemHelper;
use Box\Spout\Common\Helper\GlobalFunctionsHelper;
/**
* Class HelperFactory
* Factory to create helpers
*
* @package Box\Spout\Common\Creator
*/
class HelperFactory
{
/**
* @return GlobalFunctionsHelper
*/
public function createGlobalFunctionsHelper()
{
return new GlobalFunctionsHelper();
}
/**
* @param string $baseFolderPath The path of the base folder where all the I/O can occur
* @return FileSystemHelper
*/
public function createFileSystemHelper($baseFolderPath)
{
return new FileSystemHelper($baseFolderPath);
}
/**
* @param GlobalFunctionsHelper $globalFunctionsHelper
* @return EncodingHelper
*/
public function createEncodingHelper(GlobalFunctionsHelper $globalFunctionsHelper)
{
return new EncodingHelper($globalFunctionsHelper);
}
}

View File

@ -1,12 +1,11 @@
<?php <?php
namespace Box\Spout\Writer\Common\Manager; namespace Box\Spout\Common\Manager;
/** /**
* Class OptionsManager * Class OptionsManager
* Writer' options manager
* *
* @package Box\Spout\Writer\Common\Manager * @package Box\Spout\Common\Manager
*/ */
abstract class OptionsManagerAbstract implements OptionsManagerInterface abstract class OptionsManagerAbstract implements OptionsManagerInterface
{ {
@ -19,7 +18,7 @@ abstract class OptionsManagerAbstract implements OptionsManagerInterface
private $options = []; private $options = [];
/** /**
* WriterOptions constructor. * OptionsManagerAbstract constructor.
*/ */
public function __construct() public function __construct()
{ {

View File

@ -1,12 +1,11 @@
<?php <?php
namespace Box\Spout\Writer\Common\Manager; namespace Box\Spout\Common\Manager;
/** /**
* Interface OptionsManagerInterface * Interface OptionsManagerInterface
* Writer' options interface
* *
* @package Box\Spout\Writer\Common\Manager * @package Box\Spout\Common\Manager
*/ */
interface OptionsManagerInterface interface OptionsManagerInterface
{ {

View File

@ -0,0 +1,65 @@
<?php
namespace Box\Spout\Reader\CSV\Creator;
use Box\Spout\Common\Creator\HelperFactory;
use Box\Spout\Common\Helper\GlobalFunctionsHelper;
use Box\Spout\Common\Manager\OptionsManagerInterface;
use Box\Spout\Reader\Common\Creator\EntityFactoryInterface;
use Box\Spout\Reader\CSV\RowIterator;
use Box\Spout\Reader\CSV\Sheet;
use Box\Spout\Reader\CSV\SheetIterator;
/**
* Class EntityFactory
* Factory to create entities
*
* @package Box\Spout\Reader\CSV\Creator
*/
class EntityFactory implements EntityFactoryInterface
{
/** @var HelperFactory */
private $helperFactory;
/**
* @param HelperFactory $helperFactory
*/
public function __construct(HelperFactory $helperFactory)
{
$this->helperFactory = $helperFactory;
}
/**
* @param resource $filePointer Pointer to the CSV file to read
* @param OptionsManagerInterface $optionsManager
* @param GlobalFunctionsHelper $globalFunctionsHelper
* @return SheetIterator
*/
public function createSheetIterator($filePointer, $optionsManager, $globalFunctionsHelper)
{
return new SheetIterator($filePointer, $optionsManager, $globalFunctionsHelper, $this);
}
/**
* @param resource $filePointer Pointer to the CSV file to read
* @param OptionsManagerInterface $optionsManager
* @param GlobalFunctionsHelper $globalFunctionsHelper
* @return Sheet
*/
public function createSheet($filePointer, $optionsManager, $globalFunctionsHelper)
{
return new Sheet($filePointer, $optionsManager, $globalFunctionsHelper, $this);
}
/**
* @param resource $filePointer Pointer to the CSV file to read
* @param OptionsManagerInterface $optionsManager
* @param GlobalFunctionsHelper $globalFunctionsHelper
* @return RowIterator
*/
public function createRowIterator($filePointer, $optionsManager, $globalFunctionsHelper)
{
$encodingHelper = $this->helperFactory->createEncodingHelper($globalFunctionsHelper);
return new RowIterator($filePointer, $optionsManager, $encodingHelper, $globalFunctionsHelper);
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace Box\Spout\Reader\CSV\Manager;
use Box\Spout\Common\Helper\EncodingHelper;
use Box\Spout\Common\Manager\OptionsManagerAbstract;
use Box\Spout\Reader\Common\Entity\Options;
/**
* Class OptionsManager
* CSV Reader options manager
*
* @package Box\Spout\Reader\CSV\Manager
*/
class OptionsManager extends OptionsManagerAbstract
{
/**
* @inheritdoc
*/
protected function getSupportedOptions()
{
return [
Options::SHOULD_FORMAT_DATES,
Options::SHOULD_PRESERVE_EMPTY_ROWS,
Options::FIELD_DELIMITER,
Options::FIELD_ENCLOSURE,
Options::ENCODING,
];
}
/**
* @inheritdoc
*/
protected function setDefaultOptions()
{
$this->setOption(Options::SHOULD_FORMAT_DATES, false);
$this->setOption(Options::SHOULD_PRESERVE_EMPTY_ROWS, false);
$this->setOption(Options::FIELD_DELIMITER, ',');
$this->setOption(Options::FIELD_ENCLOSURE, '"');
$this->setOption(Options::ENCODING, EncodingHelper::ENCODING_UTF8);
}
}

View File

@ -2,7 +2,9 @@
namespace Box\Spout\Reader\CSV; namespace Box\Spout\Reader\CSV;
use Box\Spout\Reader\AbstractReader; use Box\Spout\Reader\Common\Entity\Options;
use Box\Spout\Reader\CSV\Creator\EntityFactory;
use Box\Spout\Reader\ReaderAbstract;
use Box\Spout\Common\Exception\IOException; use Box\Spout\Common\Exception\IOException;
/** /**
@ -11,7 +13,7 @@ use Box\Spout\Common\Exception\IOException;
* *
* @package Box\Spout\Reader\CSV * @package Box\Spout\Reader\CSV
*/ */
class Reader extends AbstractReader class Reader extends ReaderAbstract
{ {
/** @var resource Pointer to the file to be written */ /** @var resource Pointer to the file to be written */
protected $filePointer; protected $filePointer;
@ -22,19 +24,6 @@ class Reader extends AbstractReader
/** @var string Original value for the "auto_detect_line_endings" INI value */ /** @var string Original value for the "auto_detect_line_endings" INI value */
protected $originalAutoDetectLineEndings; protected $originalAutoDetectLineEndings;
/**
* Returns the reader's current options
*
* @return ReaderOptions
*/
protected function getOptions()
{
if (!isset($this->options)) {
$this->options = new ReaderOptions();
}
return $this->options;
}
/** /**
* Sets the field delimiter for the CSV. * Sets the field delimiter for the CSV.
* Needs to be called before opening the reader. * Needs to be called before opening the reader.
@ -44,7 +33,7 @@ class Reader extends AbstractReader
*/ */
public function setFieldDelimiter($fieldDelimiter) public function setFieldDelimiter($fieldDelimiter)
{ {
$this->getOptions()->setFieldDelimiter($fieldDelimiter); $this->optionsManager->setOption(Options::FIELD_DELIMITER, $fieldDelimiter);
return $this; return $this;
} }
@ -57,7 +46,7 @@ class Reader extends AbstractReader
*/ */
public function setFieldEnclosure($fieldEnclosure) public function setFieldEnclosure($fieldEnclosure)
{ {
$this->getOptions()->setFieldEnclosure($fieldEnclosure); $this->optionsManager->setOption(Options::FIELD_ENCLOSURE, $fieldEnclosure);
return $this; return $this;
} }
@ -70,20 +59,7 @@ class Reader extends AbstractReader
*/ */
public function setEncoding($encoding) public function setEncoding($encoding)
{ {
$this->getOptions()->setEncoding($encoding); $this->optionsManager->setOption(Options::ENCODING, $encoding);
return $this;
}
/**
* Sets the EOL for the CSV.
* Needs to be called before opening the reader.
*
* @param string $endOfLineCharacter used to properly get lines from the CSV file.
* @return Reader
*/
public function setEndOfLineCharacter($endOfLineCharacter)
{
$this->getOptions()->setEndOfLineCharacter($endOfLineCharacter);
return $this; return $this;
} }
@ -115,9 +91,12 @@ class Reader extends AbstractReader
throw new IOException("Could not open file $filePath for reading."); throw new IOException("Could not open file $filePath for reading.");
} }
$this->sheetIterator = new SheetIterator( /** @var EntityFactory $entityFactory */
$entityFactory = $this->entityFactory;
$this->sheetIterator = $entityFactory->createSheetIterator(
$this->filePointer, $this->filePointer,
$this->getOptions(), $this->optionsManager,
$this->globalFunctionsHelper $this->globalFunctionsHelper
); );
} }

View File

@ -1,110 +0,0 @@
<?php
namespace Box\Spout\Reader\CSV;
use Box\Spout\Common\Helper\EncodingHelper;
/**
* Class ReaderOptions
* This class is used to customize the reader's behavior
*
* @package Box\Spout\Reader\CSV
*/
class ReaderOptions extends \Box\Spout\Reader\Common\ReaderOptions
{
/** @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 string Encoding of the CSV file to be read */
protected $encoding = EncodingHelper::ENCODING_UTF8;
/** @var string Defines the End of line */
protected $endOfLineCharacter = "\n";
/**
* @return string
*/
public function getFieldDelimiter()
{
return $this->fieldDelimiter;
}
/**
* Sets the field delimiter for the CSV.
* Needs to be called before opening the reader.
*
* @param string $fieldDelimiter Character that delimits fields
* @return ReaderOptions
*/
public function setFieldDelimiter($fieldDelimiter)
{
$this->fieldDelimiter = $fieldDelimiter;
return $this;
}
/**
* @return string
*/
public function getFieldEnclosure()
{
return $this->fieldEnclosure;
}
/**
* Sets the field enclosure for the CSV.
* Needs to be called before opening the reader.
*
* @param string $fieldEnclosure Character that enclose fields
* @return ReaderOptions
*/
public function setFieldEnclosure($fieldEnclosure)
{
$this->fieldEnclosure = $fieldEnclosure;
return $this;
}
/**
* @return string
*/
public function getEncoding()
{
return $this->encoding;
}
/**
* Sets the encoding of the CSV file to be read.
* Needs to be called before opening the reader.
*
* @param string $encoding Encoding of the CSV file to be read
* @return ReaderOptions
*/
public function setEncoding($encoding)
{
$this->encoding = $encoding;
return $this;
}
/**
* @return string EOL for the CSV
*/
public function getEndOfLineCharacter()
{
return $this->endOfLineCharacter;
}
/**
* Sets the EOL for the CSV.
* Needs to be called before opening the reader.
*
* @param string $endOfLineCharacter used to properly get lines from the CSV file.
* @return ReaderOptions
*/
public function setEndOfLineCharacter($endOfLineCharacter)
{
$this->endOfLineCharacter = $endOfLineCharacter;
return $this;
}
}

View File

@ -2,6 +2,9 @@
namespace Box\Spout\Reader\CSV; namespace Box\Spout\Reader\CSV;
use Box\Spout\Common\Creator\HelperFactory;
use Box\Spout\Reader\Common\Entity\Options;
use Box\Spout\Reader\CSV\Creator\EntityFactory;
use Box\Spout\Reader\IteratorInterface; use Box\Spout\Reader\IteratorInterface;
use Box\Spout\Common\Helper\EncodingHelper; use Box\Spout\Common\Helper\EncodingHelper;
@ -39,9 +42,6 @@ class RowIterator implements IteratorInterface
/** @var string Encoding of the CSV file to be read */ /** @var string Encoding of the CSV file to be read */
protected $encoding; protected $encoding;
/** @var string End of line delimiter, given by the user as input. */
protected $inputEOLDelimiter;
/** @var bool Whether empty rows should be returned or skipped */ /** @var bool Whether empty rows should be returned or skipped */
protected $shouldPreserveEmptyRows; protected $shouldPreserveEmptyRows;
@ -51,25 +51,21 @@ class RowIterator implements IteratorInterface
/** @var \Box\Spout\Common\Helper\EncodingHelper Helper to work with different encodings */ /** @var \Box\Spout\Common\Helper\EncodingHelper Helper to work with different encodings */
protected $encodingHelper; protected $encodingHelper;
/** @var string End of line delimiter, encoded using the same encoding as the CSV */
protected $encodedEOLDelimiter;
/** /**
* @param resource $filePointer Pointer to the CSV file to read * @param resource $filePointer Pointer to the CSV file to read
* @param \Box\Spout\Reader\CSV\ReaderOptions $options * @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager
* @param \Box\Spout\Common\Helper\EncodingHelper $encodingHelper
* @param \Box\Spout\Common\Helper\GlobalFunctionsHelper $globalFunctionsHelper * @param \Box\Spout\Common\Helper\GlobalFunctionsHelper $globalFunctionsHelper
*/ */
public function __construct($filePointer, $options, $globalFunctionsHelper) public function __construct($filePointer, $optionsManager, $encodingHelper, $globalFunctionsHelper)
{ {
$this->filePointer = $filePointer; $this->filePointer = $filePointer;
$this->fieldDelimiter = $options->getFieldDelimiter(); $this->fieldDelimiter = $optionsManager->getOption(Options::FIELD_DELIMITER);
$this->fieldEnclosure = $options->getFieldEnclosure(); $this->fieldEnclosure = $optionsManager->getOption(Options::FIELD_ENCLOSURE);
$this->encoding = $options->getEncoding(); $this->encoding = $optionsManager->getOption(Options::ENCODING);
$this->inputEOLDelimiter = $options->getEndOfLineCharacter(); $this->shouldPreserveEmptyRows = $optionsManager->getOption(Options::SHOULD_PRESERVE_EMPTY_ROWS);
$this->shouldPreserveEmptyRows = $options->shouldPreserveEmptyRows(); $this->encodingHelper = $encodingHelper;
$this->globalFunctionsHelper = $globalFunctionsHelper; $this->globalFunctionsHelper = $globalFunctionsHelper;
$this->encodingHelper = new EncodingHelper($globalFunctionsHelper);
} }
/** /**
@ -202,21 +198,6 @@ class RowIterator implements IteratorInterface
return $encodedRowData; return $encodedRowData;
} }
/**
* Returns the end of line delimiter, encoded using the same encoding as the CSV.
* The return value is cached.
*
* @return string
*/
protected function getEncodedEOLDelimiter()
{
if (!isset($this->encodedEOLDelimiter)) {
$this->encodedEOLDelimiter = $this->encodingHelper->attemptConversionFromUTF8($this->inputEOLDelimiter, $this->encoding);
}
return $this->encodedEOLDelimiter;
}
/** /**
* @param array|bool $lineData Array containing the cells value for the line * @param array|bool $lineData Array containing the cells value for the line
* @return bool Whether the given line is empty * @return bool Whether the given line is empty

View File

@ -2,6 +2,7 @@
namespace Box\Spout\Reader\CSV; namespace Box\Spout\Reader\CSV;
use Box\Spout\Reader\CSV\Creator\EntityFactory;
use Box\Spout\Reader\SheetInterface; use Box\Spout\Reader\SheetInterface;
/** /**
@ -16,12 +17,13 @@ class Sheet implements SheetInterface
/** /**
* @param resource $filePointer Pointer to the CSV file to read * @param resource $filePointer Pointer to the CSV file to read
* @param \Box\Spout\Reader\CSV\ReaderOptions $options * @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager
* @param \Box\Spout\Common\Helper\GlobalFunctionsHelper $globalFunctionsHelper * @param \Box\Spout\Common\Helper\GlobalFunctionsHelper $globalFunctionsHelper
* @param EntityFactory $entityFactory Factory to create entities
*/ */
public function __construct($filePointer, $options, $globalFunctionsHelper) public function __construct($filePointer, $optionsManager, $globalFunctionsHelper, $entityFactory)
{ {
$this->rowIterator = new RowIterator($filePointer, $options, $globalFunctionsHelper); $this->rowIterator = $entityFactory->createRowIterator($filePointer, $optionsManager, $globalFunctionsHelper);
} }
/** /**

View File

@ -2,6 +2,7 @@
namespace Box\Spout\Reader\CSV; namespace Box\Spout\Reader\CSV;
use Box\Spout\Reader\CSV\Creator\EntityFactory;
use Box\Spout\Reader\IteratorInterface; use Box\Spout\Reader\IteratorInterface;
/** /**
@ -20,12 +21,13 @@ class SheetIterator implements IteratorInterface
/** /**
* @param resource $filePointer * @param resource $filePointer
* @param \Box\Spout\Reader\CSV\ReaderOptions $options * @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager
* @param \Box\Spout\Common\Helper\GlobalFunctionsHelper $globalFunctionsHelper * @param \Box\Spout\Common\Helper\GlobalFunctionsHelper $globalFunctionsHelper
* @param EntityFactory $entityFactory Factory to create entities
*/ */
public function __construct($filePointer, $options, $globalFunctionsHelper) public function __construct($filePointer, $optionsManager, $globalFunctionsHelper, $entityFactory)
{ {
$this->sheet = new Sheet($filePointer, $options, $globalFunctionsHelper); $this->sheet = $entityFactory->createSheet($filePointer, $optionsManager, $globalFunctionsHelper);
} }
/** /**

View File

@ -0,0 +1,12 @@
<?php
namespace Box\Spout\Reader\Common\Creator;
/**
* Interface EntityFactoryInterface
*
* @package Box\Spout\Reader\Common\Creator
*/
interface EntityFactoryInterface
{
}

View File

@ -0,0 +1,24 @@
<?php
namespace Box\Spout\Reader\Common\Entity;
/**
* Class Options
* Readers' options holder
*
* @package Box\Spout\Reader\Common\Entity
*/
abstract class Options
{
// Common options
const SHOULD_FORMAT_DATES = 'shouldFormatDates';
const SHOULD_PRESERVE_EMPTY_ROWS = 'shouldPreserveEmptyRows';
// CSV specific options
const FIELD_DELIMITER = 'fieldDelimiter';
const FIELD_ENCLOSURE = 'fieldEnclosure';
const ENCODING = 'encoding';
// XLSX specific options
const TEMP_FOLDER = 'tempFolder';
}

View File

@ -0,0 +1,90 @@
<?php
namespace Box\Spout\Reader\ODS\Creator;
use Box\Spout\Common\Helper\GlobalFunctionsHelper;
use Box\Spout\Common\Manager\OptionsManagerInterface;
use Box\Spout\Reader\Common\Creator\EntityFactoryInterface;
use Box\Spout\Reader\Common\XMLProcessor;
use Box\Spout\Reader\ODS\RowIterator;
use Box\Spout\Reader\ODS\Sheet;
use Box\Spout\Reader\ODS\SheetIterator;
use Box\Spout\Reader\Wrapper\XMLReader;
/**
* Class EntityFactory
* Factory to create entities
*
* @package Box\Spout\Reader\ODS\Creator
*/
class EntityFactory implements EntityFactoryInterface
{
/** @var HelperFactory */
private $helperFactory;
/**
* @param HelperFactory $helperFactory
*/
public function __construct(HelperFactory $helperFactory)
{
$this->helperFactory = $helperFactory;
}
/**
* @param string $filePath Path of the file to be read
* @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager Reader's options manager
* @return SheetIterator
*/
public function createSheetIterator($filePath, $optionsManager)
{
return new SheetIterator($filePath, $optionsManager, $this, $this->helperFactory);
}
/**
* @param XMLReader $xmlReader XML Reader
* @param int $sheetIndex Index of the sheet, based on order in the workbook (zero-based)
* @param string $sheetName Name of the sheet
* @param bool $isSheetActive Whether the sheet was defined as active
* @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager Reader's options manager
* @return Sheet
*/
public function createSheet($xmlReader, $sheetIndex, $sheetName, $isSheetActive, $optionsManager)
{
return new Sheet($xmlReader, $sheetIndex, $sheetName, $isSheetActive, $optionsManager, $this);
}
/**
* @param XMLReader $xmlReader XML Reader
* @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager Reader's options manager
* @return RowIterator
*/
public function createRowIterator($xmlReader, $optionsManager)
{
return new RowIterator($xmlReader, $optionsManager, $this, $this->helperFactory);
}
/**
* @return XMLReader
*/
public function createXMLReader()
{
return new XMLReader();
}
/**
* @param $xmlReader
* @return XMLProcessor
*/
public function createXMLProcessor($xmlReader)
{
return new XMLProcessor($xmlReader);
}
/**
* @return \ZipArchive
*/
public function createZipArchive()
{
return new \ZipArchive();
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace Box\Spout\Reader\ODS\Creator;
use Box\Spout\Reader\ODS\Helper\CellValueFormatter;
use Box\Spout\Reader\ODS\Helper\SettingsHelper;
/**
* Class EntityFactory
* Factory to create helpers
*
* @package Box\Spout\Reader\ODS\Creator
*/
class HelperFactory extends \Box\Spout\Common\Creator\HelperFactory
{
/**
* @param bool $shouldFormatDates Whether date/time values should be returned as PHP objects or be formatted as strings
* @return CellValueFormatter
*/
public function createCellValueFormatter($shouldFormatDates)
{
return new CellValueFormatter($shouldFormatDates);
}
/**
* @return SettingsHelper
*/
public function createSettingsHelper()
{
return new SettingsHelper();
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace Box\Spout\Reader\ODS\Manager;
use Box\Spout\Common\Manager\OptionsManagerAbstract;
use Box\Spout\Reader\Common\Entity\Options;
/**
* Class OptionsManager
* ODS Reader options manager
*
* @package Box\Spout\Reader\ODS\Manager
*/
class OptionsManager extends OptionsManagerAbstract
{
/**
* @inheritdoc
*/
protected function getSupportedOptions()
{
return [
Options::SHOULD_FORMAT_DATES,
Options::SHOULD_PRESERVE_EMPTY_ROWS,
];
}
/**
* @inheritdoc
*/
protected function setDefaultOptions()
{
$this->setOption(Options::SHOULD_FORMAT_DATES, false);
$this->setOption(Options::SHOULD_PRESERVE_EMPTY_ROWS, false);
}
}

View File

@ -3,7 +3,8 @@
namespace Box\Spout\Reader\ODS; namespace Box\Spout\Reader\ODS;
use Box\Spout\Common\Exception\IOException; use Box\Spout\Common\Exception\IOException;
use Box\Spout\Reader\AbstractReader; use Box\Spout\Reader\ODS\Creator\EntityFactory;
use Box\Spout\Reader\ReaderAbstract;
/** /**
* Class Reader * Class Reader
@ -11,7 +12,7 @@ use Box\Spout\Reader\AbstractReader;
* *
* @package Box\Spout\Reader\ODS * @package Box\Spout\Reader\ODS
*/ */
class Reader extends AbstractReader class Reader extends ReaderAbstract
{ {
/** @var \ZipArchive */ /** @var \ZipArchive */
protected $zip; protected $zip;
@ -19,19 +20,6 @@ class Reader extends AbstractReader
/** @var SheetIterator To iterator over the ODS sheets */ /** @var SheetIterator To iterator over the ODS sheets */
protected $sheetIterator; protected $sheetIterator;
/**
* Returns the reader's current options
*
* @return ReaderOptions
*/
protected function getOptions()
{
if (!isset($this->options)) {
$this->options = new ReaderOptions();
}
return $this->options;
}
/** /**
* Returns whether stream wrappers are supported * Returns whether stream wrappers are supported
* *
@ -52,10 +40,15 @@ class Reader extends AbstractReader
*/ */
protected function openReader($filePath) protected function openReader($filePath)
{ {
$this->zip = new \ZipArchive(); /** @var EntityFactory $entityFactory */
$entityFactory = $this->entityFactory;
$this->zip = $entityFactory->createZipArchive();
if ($this->zip->open($filePath) === true) { if ($this->zip->open($filePath) === true) {
$this->sheetIterator = new SheetIterator($filePath, $this->getOptions()); /** @var EntityFactory $entityFactory */
$entityFactory = $this->entityFactory;
$this->sheetIterator = $entityFactory->createSheetIterator($filePath, $this->optionsManager);
} else { } else {
throw new IOException("Could not open $filePath for reading."); throw new IOException("Could not open $filePath for reading.");
} }

View File

@ -1,14 +0,0 @@
<?php
namespace Box\Spout\Reader\ODS;
/**
* Class ReaderOptions
* This class is used to customize the reader's behavior
*
* @package Box\Spout\Reader\ODS
*/
class ReaderOptions extends \Box\Spout\Reader\Common\ReaderOptions
{
// No extra options
}

View File

@ -3,10 +3,12 @@
namespace Box\Spout\Reader\ODS; namespace Box\Spout\Reader\ODS;
use Box\Spout\Common\Exception\IOException; use Box\Spout\Common\Exception\IOException;
use Box\Spout\Reader\Common\Entity\Options;
use Box\Spout\Reader\Exception\IteratorNotRewindableException; use Box\Spout\Reader\Exception\IteratorNotRewindableException;
use Box\Spout\Reader\Exception\XMLProcessingException; use Box\Spout\Reader\Exception\XMLProcessingException;
use Box\Spout\Reader\IteratorInterface; use Box\Spout\Reader\IteratorInterface;
use Box\Spout\Reader\ODS\Helper\CellValueFormatter; use Box\Spout\Reader\ODS\Creator\EntityFactory;
use Box\Spout\Reader\ODS\Creator\HelperFactory;
use Box\Spout\Reader\Wrapper\XMLReader; use Box\Spout\Reader\Wrapper\XMLReader;
use Box\Spout\Reader\Common\XMLProcessor; use Box\Spout\Reader\Common\XMLProcessor;
@ -72,16 +74,18 @@ class RowIterator implements IteratorInterface
/** /**
* @param XMLReader $xmlReader XML Reader, positioned on the "<table:table>" element * @param XMLReader $xmlReader XML Reader, positioned on the "<table:table>" element
* @param \Box\Spout\Reader\ODS\ReaderOptions $options Reader's current options * @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager Reader's options manager
* @param EntityFactory $entityFactory Factory to create entities
* @param HelperFactory $helperFactory Factory to create helpers
*/ */
public function __construct($xmlReader, $options) public function __construct($xmlReader, $optionsManager, $entityFactory, $helperFactory)
{ {
$this->xmlReader = $xmlReader; $this->xmlReader = $xmlReader;
$this->shouldPreserveEmptyRows = $options->shouldPreserveEmptyRows(); $this->shouldPreserveEmptyRows = $optionsManager->getOption(Options::SHOULD_PRESERVE_EMPTY_ROWS);
$this->cellValueFormatter = new CellValueFormatter($options->shouldFormatDates()); $this->cellValueFormatter = $helperFactory->createCellValueFormatter($optionsManager->getOption(Options::SHOULD_FORMAT_DATES));
// Register all callbacks to process different nodes when reading the XML file // Register all callbacks to process different nodes when reading the XML file
$this->xmlProcessor = new XMLProcessor($this->xmlReader); $this->xmlProcessor = $entityFactory->createXMLProcessor($this->xmlReader);
$this->xmlProcessor->registerCallback(self::XML_NODE_ROW, XMLProcessor::NODE_TYPE_START, [$this, 'processRowStartingNode']); $this->xmlProcessor->registerCallback(self::XML_NODE_ROW, XMLProcessor::NODE_TYPE_START, [$this, 'processRowStartingNode']);
$this->xmlProcessor->registerCallback(self::XML_NODE_CELL, XMLProcessor::NODE_TYPE_START, [$this, 'processCellStartingNode']); $this->xmlProcessor->registerCallback(self::XML_NODE_CELL, XMLProcessor::NODE_TYPE_START, [$this, 'processCellStartingNode']);
$this->xmlProcessor->registerCallback(self::XML_NODE_ROW, XMLProcessor::NODE_TYPE_END, [$this, 'processRowEndingNode']); $this->xmlProcessor->registerCallback(self::XML_NODE_ROW, XMLProcessor::NODE_TYPE_END, [$this, 'processRowEndingNode']);

View File

@ -2,6 +2,7 @@
namespace Box\Spout\Reader\ODS; namespace Box\Spout\Reader\ODS;
use Box\Spout\Reader\ODS\Creator\EntityFactory;
use Box\Spout\Reader\SheetInterface; use Box\Spout\Reader\SheetInterface;
use Box\Spout\Reader\Wrapper\XMLReader; use Box\Spout\Reader\Wrapper\XMLReader;
@ -33,11 +34,12 @@ class Sheet implements SheetInterface
* @param int $sheetIndex Index of the sheet, based on order in the workbook (zero-based) * @param int $sheetIndex Index of the sheet, based on order in the workbook (zero-based)
* @param string $sheetName Name of the sheet * @param string $sheetName Name of the sheet
* @param bool $isSheetActive Whether the sheet was defined as active * @param bool $isSheetActive Whether the sheet was defined as active
* @param \Box\Spout\Reader\ODS\ReaderOptions $options Reader's current options * @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager Reader's options manager
* @param EntityFactory $entityFactory Factory to create entities
*/ */
public function __construct($xmlReader, $sheetIndex, $sheetName, $isSheetActive, $options) public function __construct($xmlReader, $sheetIndex, $sheetName, $isSheetActive, $optionsManager, $entityFactory)
{ {
$this->rowIterator = new RowIterator($xmlReader, $options); $this->rowIterator = $entityFactory->createRowIterator($xmlReader, $optionsManager);
$this->index = $sheetIndex; $this->index = $sheetIndex;
$this->name = $sheetName; $this->name = $sheetName;
$this->isActive = $isSheetActive; $this->isActive = $isSheetActive;

View File

@ -5,6 +5,8 @@ namespace Box\Spout\Reader\ODS;
use Box\Spout\Common\Exception\IOException; use Box\Spout\Common\Exception\IOException;
use Box\Spout\Reader\Exception\XMLProcessingException; use Box\Spout\Reader\Exception\XMLProcessingException;
use Box\Spout\Reader\IteratorInterface; use Box\Spout\Reader\IteratorInterface;
use Box\Spout\Reader\ODS\Creator\EntityFactory;
use Box\Spout\Reader\ODS\Creator\HelperFactory;
use Box\Spout\Reader\ODS\Helper\SettingsHelper; use Box\Spout\Reader\ODS\Helper\SettingsHelper;
use Box\Spout\Reader\Wrapper\XMLReader; use Box\Spout\Reader\Wrapper\XMLReader;
@ -25,8 +27,11 @@ class SheetIterator implements IteratorInterface
/** @var string $filePath Path of the file to be read */ /** @var string $filePath Path of the file to be read */
protected $filePath; protected $filePath;
/** @var \Box\Spout\Reader\ODS\ReaderOptions Reader's current options */ /** @var \Box\Spout\Common\Manager\OptionsManagerInterface Reader's options manager */
protected $options; protected $optionsManager;
/** @var EntityFactory $entityFactory Factory to create entities */
protected $entityFactory;
/** @var XMLReader The XMLReader object that will help read sheet's XML data */ /** @var XMLReader The XMLReader object that will help read sheet's XML data */
protected $xmlReader; protected $xmlReader;
@ -45,19 +50,21 @@ class SheetIterator implements IteratorInterface
/** /**
* @param string $filePath Path of the file to be read * @param string $filePath Path of the file to be read
* @param \Box\Spout\Reader\ODS\ReaderOptions $options Reader's current options * @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager
* @throws \Box\Spout\Reader\Exception\NoSheetsFoundException If there are no sheets in the file * @param EntityFactory $entityFactory Factory to create entities
* @param HelperFactory $helperFactory Factory to create helpers
*/ */
public function __construct($filePath, $options) public function __construct($filePath, $optionsManager, $entityFactory, $helperFactory)
{ {
$this->filePath = $filePath; $this->filePath = $filePath;
$this->options = $options; $this->optionsManager = $optionsManager;
$this->xmlReader = new XMLReader(); $this->entityFactory = $entityFactory;
$this->xmlReader = $entityFactory->createXMLReader();
/** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */ /** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */
$this->escaper = \Box\Spout\Common\Escaper\ODS::getInstance(); $this->escaper = \Box\Spout\Common\Escaper\ODS::getInstance();
$settingsHelper = new SettingsHelper(); $settingsHelper = $helperFactory->createSettingsHelper();
$this->activeSheetName = $settingsHelper->getActiveSheetName($filePath); $this->activeSheetName = $settingsHelper->getActiveSheetName($filePath);
} }
@ -124,7 +131,7 @@ class SheetIterator implements IteratorInterface
$sheetName = $this->escaper->unescape($escapedSheetName); $sheetName = $this->escaper->unescape($escapedSheetName);
$isActiveSheet = $this->isActiveSheet($sheetName, $this->currentSheetIndex, $this->activeSheetName); $isActiveSheet = $this->isActiveSheet($sheetName, $this->currentSheetIndex, $this->activeSheetName);
return new Sheet($this->xmlReader, $this->currentSheetIndex, $sheetName, $isActiveSheet, $this->options); return $this->entityFactory->createSheet($this->xmlReader, $this->currentSheetIndex, $sheetName, $isActiveSheet, $this->optionsManager);
} }
/** /**

View File

@ -3,31 +3,31 @@
namespace Box\Spout\Reader; namespace Box\Spout\Reader;
use Box\Spout\Common\Exception\IOException; use Box\Spout\Common\Exception\IOException;
use Box\Spout\Common\Helper\GlobalFunctionsHelper;
use Box\Spout\Common\Manager\OptionsManagerInterface;
use Box\Spout\Reader\Common\Creator\EntityFactoryInterface;
use Box\Spout\Reader\Common\Entity\Options;
use Box\Spout\Reader\Exception\ReaderNotOpenedException; use Box\Spout\Reader\Exception\ReaderNotOpenedException;
/** /**
* Class AbstractReader * Class ReaderAbstract
* *
* @package Box\Spout\Reader * @package Box\Spout\Reader
* @abstract * @abstract
*/ */
abstract class AbstractReader implements ReaderInterface abstract class ReaderAbstract implements ReaderInterface
{ {
/** @var bool Indicates whether the stream is currently open */ /** @var bool Indicates whether the stream is currently open */
protected $isStreamOpened = false; protected $isStreamOpened = false;
/** @var EntityFactoryInterface Factory to create entities */
protected $entityFactory;
/** @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\Reader\Common\ReaderOptions Reader's customized options */ /** @var OptionsManagerInterface Writer options manager */
protected $options; protected $optionsManager;
/**
* Returns the reader's current options
*
* @return \Box\Spout\Reader\Common\ReaderOptions
*/
abstract protected function getOptions();
/** /**
* Returns whether stream wrappers are supported * Returns whether stream wrappers are supported
@ -47,25 +47,30 @@ abstract class AbstractReader implements ReaderInterface
/** /**
* Returns an iterator to iterate over sheets. * Returns an iterator to iterate over sheets.
* *
* @return \Iterator To iterate over sheets * @return IteratorInterface To iterate over sheets
*/ */
abstract protected function getConcreteSheetIterator(); abstract protected function getConcreteSheetIterator();
/** /**
* Closes the reader. To be used after reading the file. * Closes the reader. To be used after reading the file.
* *
* @return AbstractReader * @return ReaderAbstract
*/ */
abstract protected function closeReader(); abstract protected function closeReader();
/** /**
* @param \Box\Spout\Common\Helper\GlobalFunctionsHelper $globalFunctionsHelper * @param OptionsManagerInterface $optionsManager
* @return AbstractReader * @param GlobalFunctionsHelper $globalFunctionsHelper
* @param EntityFactoryInterface $entityFactory
*/ */
public function setGlobalFunctionsHelper($globalFunctionsHelper) public function __construct(
OptionsManagerInterface $optionsManager,
GlobalFunctionsHelper $globalFunctionsHelper,
EntityFactoryInterface $entityFactory)
{ {
$this->optionsManager = $optionsManager;
$this->globalFunctionsHelper = $globalFunctionsHelper; $this->globalFunctionsHelper = $globalFunctionsHelper;
return $this; $this->entityFactory = $entityFactory;
} }
/** /**
@ -73,11 +78,11 @@ abstract class AbstractReader implements ReaderInterface
* *
* @api * @api
* @param bool $shouldFormatDates * @param bool $shouldFormatDates
* @return AbstractReader * @return ReaderAbstract
*/ */
public function setShouldFormatDates($shouldFormatDates) public function setShouldFormatDates($shouldFormatDates)
{ {
$this->getOptions()->setShouldFormatDates($shouldFormatDates); $this->optionsManager->setOption(Options::SHOULD_FORMAT_DATES, $shouldFormatDates);
return $this; return $this;
} }
@ -86,11 +91,11 @@ abstract class AbstractReader implements ReaderInterface
* *
* @api * @api
* @param bool $shouldPreserveEmptyRows * @param bool $shouldPreserveEmptyRows
* @return AbstractReader * @return ReaderAbstract
*/ */
public function setShouldPreserveEmptyRows($shouldPreserveEmptyRows) public function setShouldPreserveEmptyRows($shouldPreserveEmptyRows)
{ {
$this->getOptions()->setShouldPreserveEmptyRows($shouldPreserveEmptyRows); $this->optionsManager->setOption(Options::SHOULD_PRESERVE_EMPTY_ROWS, $shouldPreserveEmptyRows);
return $this; return $this;
} }

View File

@ -2,9 +2,11 @@
namespace Box\Spout\Reader; namespace Box\Spout\Reader;
use Box\Spout\Common\Creator\HelperFactory;
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\Reader\XLSX\Helper\SharedStringsCaching\CachingStrategyFactory;
/** /**
* Class ReaderFactory * Class ReaderFactory
@ -25,24 +27,53 @@ class ReaderFactory
*/ */
public static function create($readerType) public static function create($readerType)
{ {
$reader = null;
switch ($readerType) { switch ($readerType) {
case Type::CSV: case Type::CSV: return self::getCSVReader();
$reader = new CSV\Reader(); case Type::XLSX: return self::getXLSXReader();
break; case Type::ODS: return self::getODSReader();
case Type::XLSX:
$reader = new XLSX\Reader();
break;
case Type::ODS:
$reader = new ODS\Reader();
break;
default: default:
throw new UnsupportedTypeException('No readers supporting the given type: ' . $readerType); throw new UnsupportedTypeException('No readers supporting the given type: ' . $readerType);
} }
}
$reader->setGlobalFunctionsHelper(new GlobalFunctionsHelper()); /**
* @return CSV\Reader
*/
private static function getCSVReader()
{
$optionsManager = new CSV\Manager\OptionsManager();
$helperFactory = new HelperFactory();
$entityFactory = new CSV\Creator\EntityFactory($helperFactory);
$globalFunctionsHelper = $helperFactory->createGlobalFunctionsHelper();
return $reader; return new CSV\Reader($optionsManager, $globalFunctionsHelper, $entityFactory);
}
/**
* @return XLSX\Reader
*/
private static function getXLSXReader()
{
$optionsManager = new XLSX\Manager\OptionsManager();
$cachingStrategyFactory = new CachingStrategyFactory();
$helperFactory = new XLSX\Creator\HelperFactory($cachingStrategyFactory);
$entityFactory = new XLSX\Creator\EntityFactory($helperFactory);
$globalFunctionsHelper = $helperFactory->createGlobalFunctionsHelper();
return new XLSX\Reader($optionsManager, $globalFunctionsHelper, $entityFactory, $helperFactory);
}
/**
* @return ODS\Reader
*/
private static function getODSReader()
{
$optionsManager = new ODS\Manager\OptionsManager();
$helperFactory = new ODS\Creator\HelperFactory();
$entityFactory = new ODS\Creator\EntityFactory($helperFactory);
$globalFunctionsHelper = $helperFactory->createGlobalFunctionsHelper();
return new ODS\Reader($optionsManager, $globalFunctionsHelper, $entityFactory);
} }
} }

View File

@ -12,7 +12,7 @@ interface SheetInterface
/** /**
* Returns an iterator to iterate over the sheet's rows. * Returns an iterator to iterate over the sheet's rows.
* *
* @return \Iterator * @return IteratorInterface
*/ */
public function getRowIterator(); public function getRowIterator();
} }

View File

@ -1,7 +1,6 @@
<?php <?php
namespace Box\Spout\Reader\Wrapper; namespace Box\Spout\Reader\Wrapper;
use DOMNode;
/** /**

View File

@ -0,0 +1,118 @@
<?php
namespace Box\Spout\Reader\XLSX\Creator;
use Box\Spout\Reader\Common\Creator\EntityFactoryInterface;
use Box\Spout\Reader\Common\XMLProcessor;
use Box\Spout\Reader\XLSX\Helper\SharedStringsHelper;
use Box\Spout\Reader\XLSX\RowIterator;
use Box\Spout\Reader\XLSX\Sheet;
use Box\Spout\Reader\XLSX\SheetIterator;
use Box\Spout\Reader\Wrapper\XMLReader;
/**
* Class EntityFactory
* Factory to create entities
*
* @package Box\Spout\Reader\XLSX\Creator
*/
class EntityFactory implements EntityFactoryInterface
{
/** @var HelperFactory */
private $helperFactory;
/**
* @param HelperFactory $helperFactory
*/
public function __construct(HelperFactory $helperFactory)
{
$this->helperFactory = $helperFactory;
}
/**
* @param string $filePath Path of the file to be read
* @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager Reader's options manager
* @param SharedStringsHelper $sharedStringsHelper Helper to work with shared strings
* @param \Box\Spout\Common\Helper\GlobalFunctionsHelper $globalFunctionsHelper
* @return SheetIterator
*/
public function createSheetIterator($filePath, $optionsManager, $sharedStringsHelper, $globalFunctionsHelper)
{
return new SheetIterator(
$filePath,
$optionsManager,
$sharedStringsHelper,
$globalFunctionsHelper,
$this,
$this->helperFactory
);
}
/**
* @param string $filePath Path of the XLSX file being read
* @param string $sheetDataXMLFilePath Path of the sheet data XML file as in [Content_Types].xml
* @param int $sheetIndex Index of the sheet, based on order in the workbook (zero-based)
* @param string $sheetName Name of the sheet
* @param bool $isSheetActive Whether the sheet was defined as active
* @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager Reader's options manager
* @param SharedStringsHelper $sharedStringsHelper Helper to work with shared strings
* @return Sheet
*/
public function createSheet(
$filePath,
$sheetDataXMLFilePath,
$sheetIndex,
$sheetName,
$isSheetActive,
$optionsManager,
$sharedStringsHelper)
{
return new Sheet(
$filePath,
$sheetDataXMLFilePath,
$sheetIndex,
$sheetName,
$isSheetActive,
$optionsManager,
$sharedStringsHelper,
$this
);
}
/**
* @param string $filePath Path of the XLSX file being read
* @param string $sheetDataXMLFilePath Path of the sheet data XML file as in [Content_Types].xml
* @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager Reader's options manager
* @param SharedStringsHelper $sharedStringsHelper Helper to work with shared strings
* @return RowIterator
*/
public function createRowIterator($filePath, $sheetDataXMLFilePath, $optionsManager, $sharedStringsHelper)
{
return new RowIterator($filePath, $sheetDataXMLFilePath, $optionsManager, $sharedStringsHelper, $this, $this->helperFactory);
}
/**
* @return \ZipArchive
*/
public function createZipArchive()
{
return new \ZipArchive();
}
/**
* @return XMLReader
*/
public function createXMLReader()
{
return new XMLReader();
}
/**
* @param $xmlReader
* @return XMLProcessor
*/
public function createXMLProcessor($xmlReader)
{
return new XMLProcessor($xmlReader);
}
}

View File

@ -0,0 +1,75 @@
<?php
namespace Box\Spout\Reader\XLSX\Creator;
use Box\Spout\Reader\XLSX\Helper\CellValueFormatter;
use Box\Spout\Reader\XLSX\Helper\SharedStringsCaching\CachingStrategyFactory;
use Box\Spout\Reader\XLSX\Helper\SharedStringsHelper;
use Box\Spout\Reader\XLSX\Helper\SheetHelper;
use Box\Spout\Reader\XLSX\Helper\StyleHelper;
/**
* Class EntityFactory
* Factory to create helpers
*
* @package Box\Spout\Reader\XLSX\Creator
*/
class HelperFactory extends \Box\Spout\Common\Creator\HelperFactory
{
/** @var CachingStrategyFactory */
private $cachingStrategyFactory;
/**
* @param CachingStrategyFactory $cachingStrategyFactory Factory to create shared strings caching strategies
*/
public function __construct(CachingStrategyFactory $cachingStrategyFactory)
{
$this->cachingStrategyFactory = $cachingStrategyFactory;
}
/**
* @param string $filePath Path of the XLSX file being read
* @param string $tempFolder Temporary folder where the temporary files to store shared strings will be stored
* @param EntityFactory $entityFactory Factory to create entities
* @return SharedStringsHelper
*/
public function createSharedStringsHelper($filePath, $tempFolder, $entityFactory)
{
return new SharedStringsHelper($filePath, $tempFolder, $entityFactory, $this, $this->cachingStrategyFactory);
}
/**
* @param string $filePath Path of the XLSX file being read
* @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager Reader's options manager
* @param \Box\Spout\Reader\XLSX\Helper\SharedStringsHelper Helper to work with shared strings
* @param \Box\Spout\Common\Helper\GlobalFunctionsHelper $globalFunctionsHelper
* @param EntityFactory $entityFactory Factory to create entities
* @return SheetHelper
*/
public function createSheetHelper($filePath, $optionsManager, $sharedStringsHelper, $globalFunctionsHelper, $entityFactory)
{
return new SheetHelper($filePath, $optionsManager, $sharedStringsHelper, $globalFunctionsHelper, $entityFactory);
}
/**
* @param string $filePath Path of the XLSX file being read
* @param EntityFactory $entityFactory Factory to create entities
* @return StyleHelper
*/
public function createStyleHelper($filePath, $entityFactory)
{
return new StyleHelper($filePath, $entityFactory);
}
/**
* @param SharedStringsHelper $sharedStringsHelper Helper to work with shared strings
* @param StyleHelper $styleHelper Helper to work with styles
* @param bool $shouldFormatDates Whether date/time values should be returned as PHP objects or be formatted as strings
* @return CellValueFormatter
*/
public function createCellValueFormatter($sharedStringsHelper, $styleHelper, $shouldFormatDates)
{
return new CellValueFormatter($sharedStringsHelper, $styleHelper, $shouldFormatDates);
}
}

View File

@ -1,6 +1,7 @@
<?php <?php
namespace Box\Spout\Reader\XLSX\Helper\SharedStringsCaching; namespace Box\Spout\Reader\XLSX\Helper\SharedStringsCaching;
use Box\Spout\Reader\XLSX\Creator\HelperFactory;
/** /**
* Class CachingStrategyFactory * Class CachingStrategyFactory
@ -50,44 +51,22 @@ class CachingStrategyFactory
*/ */
const MAX_NUM_STRINGS_PER_TEMP_FILE = 10000; const MAX_NUM_STRINGS_PER_TEMP_FILE = 10000;
/** @var CachingStrategyFactory|null Singleton instance */
protected static $instance = null;
/**
* Private constructor for singleton
*/
private function __construct()
{
}
/**
* Returns the singleton instance of the factory
*
* @return CachingStrategyFactory
*/
public static function getInstance()
{
if (self::$instance === null) {
self::$instance = new CachingStrategyFactory();
}
return self::$instance;
}
/** /**
* Returns the best caching strategy, given the number of unique shared strings * Returns the best caching strategy, given the number of unique shared strings
* and the amount of memory available. * and the amount of memory available.
* *
* @param int|null $sharedStringsUniqueCount Number of unique shared strings (NULL if unknown) * @param int|null $sharedStringsUniqueCount Number of unique shared strings (NULL if unknown)
* @param string|void $tempFolder Temporary folder where the temporary files to store shared strings will be stored * @param string $tempFolder Temporary folder where the temporary files to store shared strings will be stored
* @param HelperFactory $helperFactory Factory to create helpers
* @return CachingStrategyInterface The best caching strategy * @return CachingStrategyInterface The best caching strategy
*/ */
public function getBestCachingStrategy($sharedStringsUniqueCount, $tempFolder = null) public function createBestCachingStrategy($sharedStringsUniqueCount, $tempFolder, $helperFactory)
{ {
if ($this->isInMemoryStrategyUsageSafe($sharedStringsUniqueCount)) { if ($this->isInMemoryStrategyUsageSafe($sharedStringsUniqueCount)) {
return new InMemoryStrategy($sharedStringsUniqueCount); return new InMemoryStrategy($sharedStringsUniqueCount);
} else { } else {
return new FileBasedStrategy($tempFolder, self::MAX_NUM_STRINGS_PER_TEMP_FILE); return new FileBasedStrategy($tempFolder, self::MAX_NUM_STRINGS_PER_TEMP_FILE, $helperFactory);
} }
} }

View File

@ -5,6 +5,7 @@ namespace Box\Spout\Reader\XLSX\Helper\SharedStringsCaching;
use Box\Spout\Common\Helper\FileSystemHelper; use Box\Spout\Common\Helper\FileSystemHelper;
use Box\Spout\Common\Helper\GlobalFunctionsHelper; use Box\Spout\Common\Helper\GlobalFunctionsHelper;
use Box\Spout\Reader\Exception\SharedStringNotFoundException; use Box\Spout\Reader\Exception\SharedStringNotFoundException;
use Box\Spout\Reader\XLSX\Creator\HelperFactory;
/** /**
* Class FileBasedStrategy * Class FileBasedStrategy
@ -51,18 +52,18 @@ class FileBasedStrategy implements CachingStrategyInterface
protected $inMemoryTempFileContents; protected $inMemoryTempFileContents;
/** /**
* @param string|null $tempFolder Temporary folder where the temporary files to store shared strings will be stored * @param string $tempFolder Temporary folder where the temporary files to store shared strings will be stored
* @param int $maxNumStringsPerTempFile Maximum number of strings that can be stored in one temp file * @param int $maxNumStringsPerTempFile Maximum number of strings that can be stored in one temp file
* @param HelperFactory $helperFactory Factory to create helpers
*/ */
public function __construct($tempFolder, $maxNumStringsPerTempFile) public function __construct($tempFolder, $maxNumStringsPerTempFile, $helperFactory)
{ {
$rootTempFolder = ($tempFolder) ?: sys_get_temp_dir(); $this->fileSystemHelper = $helperFactory->createFileSystemHelper($tempFolder);
$this->fileSystemHelper = new FileSystemHelper($rootTempFolder); $this->tempFolder = $this->fileSystemHelper->createFolder($tempFolder, uniqid('sharedstrings'));
$this->tempFolder = $this->fileSystemHelper->createFolder($rootTempFolder, uniqid('sharedstrings'));
$this->maxNumStringsPerTempFile = $maxNumStringsPerTempFile; $this->maxNumStringsPerTempFile = $maxNumStringsPerTempFile;
$this->globalFunctionsHelper = new GlobalFunctionsHelper(); $this->globalFunctionsHelper = $helperFactory->createGlobalFunctionsHelper();
$this->tempFilePointer = null; $this->tempFilePointer = null;
} }

View File

@ -5,6 +5,8 @@ namespace Box\Spout\Reader\XLSX\Helper;
use Box\Spout\Common\Exception\IOException; use Box\Spout\Common\Exception\IOException;
use Box\Spout\Reader\Exception\XMLProcessingException; use Box\Spout\Reader\Exception\XMLProcessingException;
use Box\Spout\Reader\Wrapper\XMLReader; use Box\Spout\Reader\Wrapper\XMLReader;
use Box\Spout\Reader\XLSX\Creator\EntityFactory;
use Box\Spout\Reader\XLSX\Creator\HelperFactory;
use Box\Spout\Reader\XLSX\Helper\SharedStringsCaching\CachingStrategyFactory; use Box\Spout\Reader\XLSX\Helper\SharedStringsCaching\CachingStrategyFactory;
use Box\Spout\Reader\XLSX\Helper\SharedStringsCaching\CachingStrategyInterface; use Box\Spout\Reader\XLSX\Helper\SharedStringsCaching\CachingStrategyInterface;
@ -40,17 +42,32 @@ class SharedStringsHelper
/** @var string Temporary folder where the temporary files to store shared strings will be stored */ /** @var string Temporary folder where the temporary files to store shared strings will be stored */
protected $tempFolder; protected $tempFolder;
/** @var EntityFactory Factory to create entities */
protected $entityFactory;
/** @var HelperFactory $helperFactory Factory to create helpers */
protected $helperFactory;
/** @var CachingStrategyFactory Factory to create shared strings caching strategies */
protected $cachingStrategyFactory;
/** @var CachingStrategyInterface The best caching strategy for storing shared strings */ /** @var CachingStrategyInterface The best caching strategy for storing shared strings */
protected $cachingStrategy; protected $cachingStrategy;
/** /**
* @param string $filePath Path of the XLSX file being read * @param string $filePath Path of the XLSX file being read
* @param string|null|void $tempFolder Temporary folder where the temporary files to store shared strings will be stored * @param string $tempFolder Temporary folder where the temporary files to store shared strings will be stored
* @param EntityFactory $entityFactory Factory to create entities
* @param HelperFactory $helperFactory Factory to create helpers
* @param CachingStrategyFactory $cachingStrategyFactory Factory to create shared strings caching strategies
*/ */
public function __construct($filePath, $tempFolder = null) public function __construct($filePath, $tempFolder, $entityFactory, $helperFactory, $cachingStrategyFactory)
{ {
$this->filePath = $filePath; $this->filePath = $filePath;
$this->tempFolder = $tempFolder; $this->tempFolder = $tempFolder;
$this->entityFactory = $entityFactory;
$this->helperFactory = $helperFactory;
$this->cachingStrategyFactory = $cachingStrategyFactory;
} }
/** /**
@ -61,7 +78,7 @@ class SharedStringsHelper
public function hasSharedStrings() public function hasSharedStrings()
{ {
$hasSharedStrings = false; $hasSharedStrings = false;
$zip = new \ZipArchive(); $zip = $this->entityFactory->createZipArchive();
if ($zip->open($this->filePath) === true) { if ($zip->open($this->filePath) === true) {
$hasSharedStrings = ($zip->locateName(self::SHARED_STRINGS_XML_FILE_PATH) !== false); $hasSharedStrings = ($zip->locateName(self::SHARED_STRINGS_XML_FILE_PATH) !== false);
@ -86,7 +103,7 @@ class SharedStringsHelper
*/ */
public function extractSharedStrings() public function extractSharedStrings()
{ {
$xmlReader = new XMLReader(); $xmlReader = $this->entityFactory->createXMLReader();
$sharedStringIndex = 0; $sharedStringIndex = 0;
if ($xmlReader->openFileInZip($this->filePath, self::SHARED_STRINGS_XML_FILE_PATH) === false) { if ($xmlReader->openFileInZip($this->filePath, self::SHARED_STRINGS_XML_FILE_PATH) === false) {
@ -151,8 +168,8 @@ class SharedStringsHelper
*/ */
protected function getBestSharedStringsCachingStrategy($sharedStringsUniqueCount) protected function getBestSharedStringsCachingStrategy($sharedStringsUniqueCount)
{ {
return CachingStrategyFactory::getInstance() return $this->cachingStrategyFactory
->getBestCachingStrategy($sharedStringsUniqueCount, $this->tempFolder); ->createBestCachingStrategy($sharedStringsUniqueCount, $this->tempFolder, $this->helperFactory);
} }
/** /**

View File

@ -3,6 +3,7 @@
namespace Box\Spout\Reader\XLSX\Helper; namespace Box\Spout\Reader\XLSX\Helper;
use Box\Spout\Reader\Wrapper\XMLReader; use Box\Spout\Reader\Wrapper\XMLReader;
use Box\Spout\Reader\XLSX\Creator\EntityFactory;
use Box\Spout\Reader\XLSX\Sheet; use Box\Spout\Reader\XLSX\Sheet;
/** /**
@ -33,8 +34,8 @@ class SheetHelper
/** @var string Path of the XLSX file being read */ /** @var string Path of the XLSX file being read */
protected $filePath; protected $filePath;
/** @var \Box\Spout\Reader\XLSX\ReaderOptions Reader's current options */ /** @var \Box\Spout\Common\Manager\OptionsManagerInterface Reader's options manager */
protected $options; protected $optionsManager;
/** @var \Box\Spout\Reader\XLSX\Helper\SharedStringsHelper Helper to work with shared strings */ /** @var \Box\Spout\Reader\XLSX\Helper\SharedStringsHelper Helper to work with shared strings */
protected $sharedStringsHelper; protected $sharedStringsHelper;
@ -42,18 +43,23 @@ class SheetHelper
/** @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 EntityFactory Factory to create entities */
protected $entityFactory;
/** /**
* @param string $filePath Path of the XLSX file being read * @param string $filePath Path of the XLSX file being read
* @param \Box\Spout\Reader\XLSX\ReaderOptions $options Reader's current options * @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager Reader's options manager
* @param \Box\Spout\Reader\XLSX\Helper\SharedStringsHelper Helper to work with shared strings * @param \Box\Spout\Reader\XLSX\Helper\SharedStringsHelper Helper to work with shared strings
* @param \Box\Spout\Common\Helper\GlobalFunctionsHelper $globalFunctionsHelper * @param \Box\Spout\Common\Helper\GlobalFunctionsHelper $globalFunctionsHelper
* @param EntityFactory $entityFactory Factory to create entities
*/ */
public function __construct($filePath, $options, $sharedStringsHelper, $globalFunctionsHelper) public function __construct($filePath, $optionsManager, $sharedStringsHelper, $globalFunctionsHelper, $entityFactory)
{ {
$this->filePath = $filePath; $this->filePath = $filePath;
$this->options = $options; $this->optionsManager = $optionsManager;
$this->sharedStringsHelper = $sharedStringsHelper; $this->sharedStringsHelper = $sharedStringsHelper;
$this->globalFunctionsHelper = $globalFunctionsHelper; $this->globalFunctionsHelper = $globalFunctionsHelper;
$this->entityFactory = $entityFactory;
} }
/** /**
@ -68,7 +74,8 @@ class SheetHelper
$sheetIndex = 0; $sheetIndex = 0;
$activeSheetIndex = 0; // By default, the first sheet is active $activeSheetIndex = 0; // By default, the first sheet is active
$xmlReader = new XMLReader(); $xmlReader = $this->entityFactory->createXMLReader();
if ($xmlReader->openFileInZip($this->filePath, self::WORKBOOK_XML_FILE_PATH)) { if ($xmlReader->openFileInZip($this->filePath, self::WORKBOOK_XML_FILE_PATH)) {
while ($xmlReader->read()) { while ($xmlReader->read()) {
if ($xmlReader->isPositionedOnStartingNode(self::XML_NODE_WORKBOOK_VIEW)) { if ($xmlReader->isPositionedOnStartingNode(self::XML_NODE_WORKBOOK_VIEW)) {
@ -112,10 +119,14 @@ class SheetHelper
$sheetDataXMLFilePath = $this->getSheetDataXMLFilePathForSheetId($sheetId); $sheetDataXMLFilePath = $this->getSheetDataXMLFilePathForSheetId($sheetId);
return new Sheet( return $this->entityFactory->createSheet(
$this->filePath, $sheetDataXMLFilePath, $this->filePath,
$sheetIndexZeroBased, $sheetName, $isSheetActive, $sheetDataXMLFilePath,
$this->options, $this->sharedStringsHelper $sheetIndexZeroBased,
$sheetName,
$isSheetActive,
$this->optionsManager,
$this->sharedStringsHelper
); );
} }
@ -128,7 +139,7 @@ class SheetHelper
$sheetDataXMLFilePath = ''; $sheetDataXMLFilePath = '';
// find the file path of the sheet, by looking at the "workbook.xml.res" file // find the file path of the sheet, by looking at the "workbook.xml.res" file
$xmlReader = new XMLReader(); $xmlReader = $this->entityFactory->createXMLReader();
if ($xmlReader->openFileInZip($this->filePath, self::WORKBOOK_XML_RELS_FILE_PATH)) { if ($xmlReader->openFileInZip($this->filePath, self::WORKBOOK_XML_RELS_FILE_PATH)) {
while ($xmlReader->read()) { while ($xmlReader->read()) {
if ($xmlReader->isPositionedOnStartingNode(self::XML_NODE_RELATIONSHIP)) { if ($xmlReader->isPositionedOnStartingNode(self::XML_NODE_RELATIONSHIP)) {

View File

@ -2,7 +2,7 @@
namespace Box\Spout\Reader\XLSX\Helper; namespace Box\Spout\Reader\XLSX\Helper;
use Box\Spout\Reader\Wrapper\XMLReader; use Box\Spout\Reader\XLSX\Creator\EntityFactory;
/** /**
* Class StyleHelper * Class StyleHelper
@ -53,6 +53,9 @@ class StyleHelper
/** @var string Path of the XLSX file being read */ /** @var string Path of the XLSX file being read */
protected $filePath; protected $filePath;
/** @var EntityFactory Factory to create entities */
protected $entityFactory;
/** @var array Array containing the IDs of built-in number formats indicating a date */ /** @var array Array containing the IDs of built-in number formats indicating a date */
protected $builtinNumFmtIdIndicatingDates; protected $builtinNumFmtIdIndicatingDates;
@ -67,10 +70,12 @@ class StyleHelper
/** /**
* @param string $filePath Path of the XLSX file being read * @param string $filePath Path of the XLSX file being read
* @param EntityFactory $entityFactory Factory to create entities
*/ */
public function __construct($filePath) public function __construct($filePath, $entityFactory)
{ {
$this->filePath = $filePath; $this->filePath = $filePath;
$this->entityFactory = $entityFactory;
$this->builtinNumFmtIdIndicatingDates = array_keys(self::$builtinNumFmtIdToNumFormatMapping); $this->builtinNumFmtIdIndicatingDates = array_keys(self::$builtinNumFmtIdToNumFormatMapping);
} }
@ -107,7 +112,7 @@ class StyleHelper
$this->customNumberFormats = []; $this->customNumberFormats = [];
$this->stylesAttributes = []; $this->stylesAttributes = [];
$xmlReader = new XMLReader(); $xmlReader = $this->entityFactory->createXMLReader();
if ($xmlReader->openFileInZip($this->filePath, self::STYLES_XML_FILE_PATH)) { if ($xmlReader->openFileInZip($this->filePath, self::STYLES_XML_FILE_PATH)) {
while ($xmlReader->read()) { while ($xmlReader->read()) {

View File

@ -0,0 +1,37 @@
<?php
namespace Box\Spout\Reader\XLSX\Manager;
use Box\Spout\Common\Manager\OptionsManagerAbstract;
use Box\Spout\Reader\Common\Entity\Options;
/**
* Class OptionsManager
* XLSX Reader options manager
*
* @package Box\Spout\Reader\XLSX\Manager
*/
class OptionsManager extends OptionsManagerAbstract
{
/**
* @inheritdoc
*/
protected function getSupportedOptions()
{
return [
Options::TEMP_FOLDER,
Options::SHOULD_FORMAT_DATES,
Options::SHOULD_PRESERVE_EMPTY_ROWS,
];
}
/**
* @inheritdoc
*/
protected function setDefaultOptions()
{
$this->setOption(Options::TEMP_FOLDER, sys_get_temp_dir());
$this->setOption(Options::SHOULD_FORMAT_DATES, false);
$this->setOption(Options::SHOULD_PRESERVE_EMPTY_ROWS, false);
}
}

View File

@ -3,8 +3,13 @@
namespace Box\Spout\Reader\XLSX; namespace Box\Spout\Reader\XLSX;
use Box\Spout\Common\Exception\IOException; use Box\Spout\Common\Exception\IOException;
use Box\Spout\Reader\AbstractReader; use Box\Spout\Common\Helper\GlobalFunctionsHelper;
use Box\Spout\Reader\XLSX\Helper\SharedStringsHelper; use Box\Spout\Common\Manager\OptionsManagerInterface;
use Box\Spout\Reader\Common\Creator\EntityFactoryInterface;
use Box\Spout\Reader\Common\Entity\Options;
use Box\Spout\Reader\ReaderAbstract;
use Box\Spout\Reader\XLSX\Creator\EntityFactory;
use Box\Spout\Reader\XLSX\Creator\HelperFactory;
/** /**
* Class Reader * Class Reader
@ -12,8 +17,11 @@ use Box\Spout\Reader\XLSX\Helper\SharedStringsHelper;
* *
* @package Box\Spout\Reader\XLSX * @package Box\Spout\Reader\XLSX
*/ */
class Reader extends AbstractReader class Reader extends ReaderAbstract
{ {
/** @var HelperFactory */
protected $helperFactory;
/** @var \ZipArchive */ /** @var \ZipArchive */
protected $zip; protected $zip;
@ -25,16 +33,19 @@ class Reader extends AbstractReader
/** /**
* Returns the reader's current options * @param OptionsManagerInterface $optionsManager
* * @param GlobalFunctionsHelper $globalFunctionsHelper
* @return ReaderOptions * @param EntityFactoryInterface $entityFactory
* @param HelperFactory $helperFactory
*/ */
protected function getOptions() public function __construct(
OptionsManagerInterface $optionsManager,
GlobalFunctionsHelper $globalFunctionsHelper,
EntityFactoryInterface $entityFactory,
HelperFactory $helperFactory)
{ {
if (!isset($this->options)) { parent::__construct($optionsManager, $globalFunctionsHelper, $entityFactory);
$this->options = new ReaderOptions(); $this->helperFactory = $helperFactory;
}
return $this->options;
} }
/** /**
@ -43,7 +54,7 @@ class Reader extends AbstractReader
*/ */
public function setTempFolder($tempFolder) public function setTempFolder($tempFolder)
{ {
$this->getOptions()->setTempFolder($tempFolder); $this->optionsManager->setOption(Options::TEMP_FOLDER, $tempFolder);
return $this; return $this;
} }
@ -69,17 +80,21 @@ class Reader extends AbstractReader
*/ */
protected function openReader($filePath) protected function openReader($filePath)
{ {
$this->zip = new \ZipArchive(); /** @var EntityFactory $entityFactory */
$entityFactory = $this->entityFactory;
$this->zip = $entityFactory->createZipArchive();
if ($this->zip->open($filePath) === true) { if ($this->zip->open($filePath) === true) {
$this->sharedStringsHelper = new SharedStringsHelper($filePath, $this->getOptions()->getTempFolder()); $tempFolder = $this->optionsManager->getOption(Options::TEMP_FOLDER);
$this->sharedStringsHelper = $this->helperFactory->createSharedStringsHelper($filePath, $tempFolder, $entityFactory);
if ($this->sharedStringsHelper->hasSharedStrings()) { if ($this->sharedStringsHelper->hasSharedStrings()) {
// Extracts all the strings from the sheets for easy access in the future // Extracts all the strings from the sheets for easy access in the future
$this->sharedStringsHelper->extractSharedStrings(); $this->sharedStringsHelper->extractSharedStrings();
} }
$this->sheetIterator = new SheetIterator($filePath, $this->getOptions(), $this->sharedStringsHelper, $this->globalFunctionsHelper); $this->sheetIterator = $entityFactory->createSheetIterator($filePath, $this->optionsManager, $this->sharedStringsHelper, $this->globalFunctionsHelper);
} else { } else {
throw new IOException("Could not open $filePath for reading."); throw new IOException("Could not open $filePath for reading.");
} }

View File

@ -1,33 +0,0 @@
<?php
namespace Box\Spout\Reader\XLSX;
/**
* Class ReaderOptions
* This class is used to customize the reader's behavior
*
* @package Box\Spout\Reader\XLSX
*/
class ReaderOptions extends \Box\Spout\Reader\Common\ReaderOptions
{
/** @var string|null Temporary folder where the temporary files will be created */
protected $tempFolder = null;
/**
* @return string|null Temporary folder where the temporary files will be created
*/
public function getTempFolder()
{
return $this->tempFolder;
}
/**
* @param string|null $tempFolder Temporary folder where the temporary files will be created
* @return ReaderOptions
*/
public function setTempFolder($tempFolder)
{
$this->tempFolder = $tempFolder;
return $this;
}
}

View File

@ -3,9 +3,12 @@
namespace Box\Spout\Reader\XLSX; namespace Box\Spout\Reader\XLSX;
use Box\Spout\Common\Exception\IOException; use Box\Spout\Common\Exception\IOException;
use Box\Spout\Reader\Common\Entity\Options;
use Box\Spout\Reader\Exception\XMLProcessingException; use Box\Spout\Reader\Exception\XMLProcessingException;
use Box\Spout\Reader\IteratorInterface; use Box\Spout\Reader\IteratorInterface;
use Box\Spout\Reader\Wrapper\XMLReader; use Box\Spout\Reader\Wrapper\XMLReader;
use Box\Spout\Reader\XLSX\Creator\EntityFactory;
use Box\Spout\Reader\XLSX\Creator\HelperFactory;
use Box\Spout\Reader\XLSX\Helper\CellHelper; use Box\Spout\Reader\XLSX\Helper\CellHelper;
use Box\Spout\Reader\XLSX\Helper\CellValueFormatter; use Box\Spout\Reader\XLSX\Helper\CellValueFormatter;
use Box\Spout\Reader\XLSX\Helper\StyleHelper; use Box\Spout\Reader\XLSX\Helper\StyleHelper;
@ -81,23 +84,25 @@ class RowIterator implements IteratorInterface
/** /**
* @param string $filePath Path of the XLSX file being read * @param string $filePath Path of the XLSX file being read
* @param string $sheetDataXMLFilePath Path of the sheet data XML file as in [Content_Types].xml * @param string $sheetDataXMLFilePath Path of the sheet data XML file as in [Content_Types].xml
* @param \Box\Spout\Reader\XLSX\ReaderOptions $options Reader's current options * @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager Reader's options manager
* @param Helper\SharedStringsHelper $sharedStringsHelper Helper to work with shared strings * @param Helper\SharedStringsHelper $sharedStringsHelper Helper to work with shared strings
* @param EntityFactory $entityFactory Factory to create entities
* @param HelperFactory $helperFactory Factory to create helpers
*/ */
public function __construct($filePath, $sheetDataXMLFilePath, $options, $sharedStringsHelper) public function __construct($filePath, $sheetDataXMLFilePath, $optionsManager, $sharedStringsHelper, $entityFactory, $helperFactory)
{ {
$this->filePath = $filePath; $this->filePath = $filePath;
$this->sheetDataXMLFilePath = $this->normalizeSheetDataXMLFilePath($sheetDataXMLFilePath); $this->sheetDataXMLFilePath = $this->normalizeSheetDataXMLFilePath($sheetDataXMLFilePath);
$this->xmlReader = new XMLReader(); $this->xmlReader = $entityFactory->createXMLReader();
$this->styleHelper = new StyleHelper($filePath); $this->styleHelper = $helperFactory->createStyleHelper($filePath, $entityFactory);
$this->cellValueFormatter = new CellValueFormatter($sharedStringsHelper, $this->styleHelper, $options->shouldFormatDates()); $this->cellValueFormatter = $helperFactory->createCellValueFormatter($sharedStringsHelper, $this->styleHelper, $optionsManager->getOption(Options::SHOULD_FORMAT_DATES));
$this->shouldPreserveEmptyRows = $options->shouldPreserveEmptyRows(); $this->shouldPreserveEmptyRows = $optionsManager->getOption(Options::SHOULD_PRESERVE_EMPTY_ROWS);
// Register all callbacks to process different nodes when reading the XML file // Register all callbacks to process different nodes when reading the XML file
$this->xmlProcessor = new XMLProcessor($this->xmlReader); $this->xmlProcessor = $entityFactory->createXMLProcessor($this->xmlReader);
$this->xmlProcessor->registerCallback(self::XML_NODE_DIMENSION, XMLProcessor::NODE_TYPE_START, [$this, 'processDimensionStartingNode']); $this->xmlProcessor->registerCallback(self::XML_NODE_DIMENSION, XMLProcessor::NODE_TYPE_START, [$this, 'processDimensionStartingNode']);
$this->xmlProcessor->registerCallback(self::XML_NODE_ROW, XMLProcessor::NODE_TYPE_START, [$this, 'processRowStartingNode']); $this->xmlProcessor->registerCallback(self::XML_NODE_ROW, XMLProcessor::NODE_TYPE_START, [$this, 'processRowStartingNode']);
$this->xmlProcessor->registerCallback(self::XML_NODE_CELL, XMLProcessor::NODE_TYPE_START, [$this, 'processCellStartingNode']); $this->xmlProcessor->registerCallback(self::XML_NODE_CELL, XMLProcessor::NODE_TYPE_START, [$this, 'processCellStartingNode']);

View File

@ -3,6 +3,7 @@
namespace Box\Spout\Reader\XLSX; namespace Box\Spout\Reader\XLSX;
use Box\Spout\Reader\SheetInterface; use Box\Spout\Reader\SheetInterface;
use Box\Spout\Reader\XLSX\Creator\EntityFactory;
/** /**
* Class Sheet * Class Sheet
@ -30,12 +31,20 @@ class Sheet implements SheetInterface
* @param int $sheetIndex Index of the sheet, based on order in the workbook (zero-based) * @param int $sheetIndex Index of the sheet, based on order in the workbook (zero-based)
* @param string $sheetName Name of the sheet * @param string $sheetName Name of the sheet
* @param bool $isSheetActive Whether the sheet was defined as active * @param bool $isSheetActive Whether the sheet was defined as active
* @param \Box\Spout\Reader\XLSX\ReaderOptions $options Reader's current options * @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager Reader's options manager
* @param Helper\SharedStringsHelper Helper to work with shared strings * @param Helper\SharedStringsHelper $sharedStringsHelper Helper to work with shared strings
* @param EntityFactory $entityFactory Factory to create entities
*/ */
public function __construct($filePath, $sheetDataXMLFilePath, $sheetIndex, $sheetName, $isSheetActive, $options, $sharedStringsHelper) public function __construct(
$filePath,
$sheetDataXMLFilePath,
$sheetIndex, $sheetName,
$isSheetActive,
$optionsManager,
$sharedStringsHelper,
$entityFactory)
{ {
$this->rowIterator = new RowIterator($filePath, $sheetDataXMLFilePath, $options, $sharedStringsHelper); $this->rowIterator = $entityFactory->createRowIterator($filePath, $sheetDataXMLFilePath, $optionsManager, $sharedStringsHelper);
$this->index = $sheetIndex; $this->index = $sheetIndex;
$this->name = $sheetName; $this->name = $sheetName;
$this->isActive = $isSheetActive; $this->isActive = $isSheetActive;

View File

@ -3,6 +3,8 @@
namespace Box\Spout\Reader\XLSX; namespace Box\Spout\Reader\XLSX;
use Box\Spout\Reader\IteratorInterface; use Box\Spout\Reader\IteratorInterface;
use Box\Spout\Reader\XLSX\Creator\EntityFactory;
use Box\Spout\Reader\XLSX\Creator\HelperFactory;
use Box\Spout\Reader\XLSX\Helper\SheetHelper; use Box\Spout\Reader\XLSX\Helper\SheetHelper;
use Box\Spout\Reader\Exception\NoSheetsFoundException; use Box\Spout\Reader\Exception\NoSheetsFoundException;
@ -22,15 +24,23 @@ class SheetIterator implements IteratorInterface
/** /**
* @param string $filePath Path of the file to be read * @param string $filePath Path of the file to be read
* @param \Box\Spout\Reader\XLSX\ReaderOptions $options Reader's current options * @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager Reader's options manager
* @param \Box\Spout\Reader\XLSX\Helper\SharedStringsHelper $sharedStringsHelper * @param \Box\Spout\Reader\XLSX\Helper\SharedStringsHelper $sharedStringsHelper
* @param \Box\Spout\Common\Helper\GlobalFunctionsHelper $globalFunctionsHelper * @param \Box\Spout\Common\Helper\GlobalFunctionsHelper $globalFunctionsHelper
* @param EntityFactory $entityFactory Factory to create entities
* @param HelperFactory $helperFactory Factory to create helpers
* @throws \Box\Spout\Reader\Exception\NoSheetsFoundException If there are no sheets in the file * @throws \Box\Spout\Reader\Exception\NoSheetsFoundException If there are no sheets in the file
*/ */
public function __construct($filePath, $options, $sharedStringsHelper, $globalFunctionsHelper) public function __construct(
$filePath,
$optionsManager,
$sharedStringsHelper,
$globalFunctionsHelper,
$entityFactory,
$helperFactory)
{ {
// Fetch all available sheets // Fetch all available sheets
$sheetHelper = new SheetHelper($filePath, $options, $sharedStringsHelper, $globalFunctionsHelper); $sheetHelper = $helperFactory->createSheetHelper($filePath, $optionsManager, $sharedStringsHelper, $globalFunctionsHelper, $entityFactory);
$this->sheets = $sheetHelper->getSheets(); $this->sheets = $sheetHelper->getSheets();
if (count($this->sheets) === 0) { if (count($this->sheets) === 0) {

View File

@ -3,7 +3,7 @@
namespace Box\Spout\Writer\CSV\Manager; namespace Box\Spout\Writer\CSV\Manager;
use Box\Spout\Writer\Common\Entity\Options; use Box\Spout\Writer\Common\Entity\Options;
use Box\Spout\Writer\Common\Manager\OptionsManagerAbstract; use Box\Spout\Common\Manager\OptionsManagerAbstract;
/** /**
* Class OptionsManager * Class OptionsManager

View File

@ -2,7 +2,7 @@
namespace Box\Spout\Writer\Common\Creator; namespace Box\Spout\Writer\Common\Creator;
use Box\Spout\Writer\Common\Manager\OptionsManagerInterface; use Box\Spout\Common\Manager\OptionsManagerInterface;
use Box\Spout\Writer\Common\Manager\WorkbookManagerInterface; use Box\Spout\Writer\Common\Manager\WorkbookManagerInterface;
/** /**

View File

@ -4,7 +4,7 @@ namespace Box\Spout\Writer\Common\Entity;
/** /**
* Class Options * Class Options
* Writer' options holder * Writers' options holder
* *
* @package Box\Spout\Writer\Common\Entity * @package Box\Spout\Writer\Common\Entity
*/ */

View File

@ -3,6 +3,7 @@
namespace Box\Spout\Writer\Common\Manager; namespace Box\Spout\Writer\Common\Manager;
use Box\Spout\Common\Exception\IOException; use Box\Spout\Common\Exception\IOException;
use Box\Spout\Common\Manager\OptionsManagerInterface;
use Box\Spout\Writer\Common\Helper\FileSystemWithRootFolderHelperInterface; use Box\Spout\Writer\Common\Helper\FileSystemWithRootFolderHelperInterface;
use Box\Spout\Writer\Common\Entity\Options; use Box\Spout\Writer\Common\Entity\Options;
use Box\Spout\Writer\Common\Manager\Style\StyleManagerInterface; use Box\Spout\Writer\Common\Manager\Style\StyleManagerInterface;

View File

@ -4,7 +4,7 @@ namespace Box\Spout\Writer\ODS\Creator;
use Box\Spout\Common\Helper\StringHelper; use Box\Spout\Common\Helper\StringHelper;
use Box\Spout\Writer\Common\Helper\ZipHelper; use Box\Spout\Writer\Common\Helper\ZipHelper;
use Box\Spout\Writer\Common\Manager\OptionsManagerInterface; use Box\Spout\Common\Manager\OptionsManagerInterface;
use Box\Spout\Writer\Common\Entity\Options; use Box\Spout\Writer\Common\Entity\Options;
use Box\Spout\Writer\Common\Creator\EntityFactory; use Box\Spout\Writer\Common\Creator\EntityFactory;
use Box\Spout\Writer\Common\Creator\InternalFactoryInterface; use Box\Spout\Writer\Common\Creator\InternalFactoryInterface;

View File

@ -3,7 +3,7 @@
namespace Box\Spout\Writer\ODS\Manager; namespace Box\Spout\Writer\ODS\Manager;
use Box\Spout\Writer\Common\Entity\Options; use Box\Spout\Writer\Common\Entity\Options;
use Box\Spout\Writer\Common\Manager\OptionsManagerAbstract; use Box\Spout\Common\Manager\OptionsManagerAbstract;
use Box\Spout\Writer\Common\Creator\Style\StyleBuilder; use Box\Spout\Writer\Common\Creator\Style\StyleBuilder;
/** /**

View File

@ -9,7 +9,7 @@ use Box\Spout\Common\Helper\FileSystemHelper;
use Box\Spout\Common\Helper\GlobalFunctionsHelper; use Box\Spout\Common\Helper\GlobalFunctionsHelper;
use Box\Spout\Writer\Common\Entity\Options; use Box\Spout\Writer\Common\Entity\Options;
use Box\Spout\Writer\Common\Entity\Style\Style; use Box\Spout\Writer\Common\Entity\Style\Style;
use Box\Spout\Writer\Common\Manager\OptionsManagerInterface; use Box\Spout\Common\Manager\OptionsManagerInterface;
use Box\Spout\Writer\Common\Manager\Style\StyleMerger; use Box\Spout\Writer\Common\Manager\Style\StyleMerger;
use Box\Spout\Writer\Exception\WriterAlreadyOpenedException; use Box\Spout\Writer\Exception\WriterAlreadyOpenedException;
use Box\Spout\Writer\Exception\WriterNotOpenedException; use Box\Spout\Writer\Exception\WriterNotOpenedException;

View File

@ -4,7 +4,7 @@ namespace Box\Spout\Writer;
use Box\Spout\Common\Helper\GlobalFunctionsHelper; use Box\Spout\Common\Helper\GlobalFunctionsHelper;
use Box\Spout\Writer\Common\Entity\Sheet; use Box\Spout\Writer\Common\Entity\Sheet;
use Box\Spout\Writer\Common\Manager\OptionsManagerInterface; use Box\Spout\Common\Manager\OptionsManagerInterface;
use Box\Spout\Writer\Common\Entity\Options; use Box\Spout\Writer\Common\Entity\Options;
use Box\Spout\Writer\Common\Entity\Worksheet; use Box\Spout\Writer\Common\Entity\Worksheet;
use Box\Spout\Writer\Common\Manager\Style\StyleMerger; use Box\Spout\Writer\Common\Manager\Style\StyleMerger;

View File

@ -8,7 +8,7 @@ use Box\Spout\Writer\Common\Creator\EntityFactory;
use Box\Spout\Writer\Common\Creator\InternalFactoryInterface; use Box\Spout\Writer\Common\Creator\InternalFactoryInterface;
use Box\Spout\Writer\Common\Entity\Options; use Box\Spout\Writer\Common\Entity\Options;
use Box\Spout\Writer\Common\Helper\ZipHelper; use Box\Spout\Writer\Common\Helper\ZipHelper;
use Box\Spout\Writer\Common\Manager\OptionsManagerInterface; use Box\Spout\Common\Manager\OptionsManagerInterface;
use Box\Spout\Writer\XLSX\Helper\FileSystemHelper; use Box\Spout\Writer\XLSX\Helper\FileSystemHelper;
use Box\Spout\Writer\XLSX\Manager\SharedStringsManager; use Box\Spout\Writer\XLSX\Manager\SharedStringsManager;
use Box\Spout\Writer\XLSX\Manager\Style\StyleManager; use Box\Spout\Writer\XLSX\Manager\Style\StyleManager;

View File

@ -3,7 +3,7 @@
namespace Box\Spout\Writer\XLSX\Manager; namespace Box\Spout\Writer\XLSX\Manager;
use Box\Spout\Writer\Common\Entity\Options; use Box\Spout\Writer\Common\Entity\Options;
use Box\Spout\Writer\Common\Manager\OptionsManagerAbstract; use Box\Spout\Common\Manager\OptionsManagerAbstract;
use Box\Spout\Writer\Common\Creator\Style\StyleBuilder; use Box\Spout\Writer\Common\Creator\Style\StyleBuilder;
/** /**

View File

@ -6,7 +6,7 @@ use Box\Spout\Common\Exception\InvalidArgumentException;
use Box\Spout\Common\Exception\IOException; use Box\Spout\Common\Exception\IOException;
use Box\Spout\Common\Helper\StringHelper; use Box\Spout\Common\Helper\StringHelper;
use Box\Spout\Writer\Common\Helper\CellHelper; use Box\Spout\Writer\Common\Helper\CellHelper;
use Box\Spout\Writer\Common\Manager\OptionsManagerInterface; use Box\Spout\Common\Manager\OptionsManagerInterface;
use Box\Spout\Writer\Common\Entity\Options; use Box\Spout\Writer\Common\Entity\Options;
use Box\Spout\Writer\Common\Entity\Cell; use Box\Spout\Writer\Common\Entity\Cell;
use Box\Spout\Writer\Common\Entity\Worksheet; use Box\Spout\Writer\Common\Entity\Worksheet;

View File

@ -1,11 +1,11 @@
<?php <?php
namespace Box\Spout\Writer\Common\Manager; namespace Box\Spout\Common\Manager;
/** /**
* Class OptionsManagerTest * Class OptionsManagerTest
* *
* @package Box\Spout\Writer\Common\Manager * @package Box\Spout\Common\Manager
*/ */
class OptionsManagerTest extends \PHPUnit_Framework_TestCase class OptionsManagerTest extends \PHPUnit_Framework_TestCase
{ {

View File

@ -2,9 +2,14 @@
namespace Box\Spout\Reader\CSV; namespace Box\Spout\Reader\CSV;
use Box\Spout\Common\Creator\HelperFactory;
use Box\Spout\Common\Helper\GlobalFunctionsHelper;
use Box\Spout\Reader\CSV\Creator\EntityFactory;
use Box\Spout\Reader\CSV\Manager\OptionsManager;
use Box\Spout\Reader\ReaderFactory; use Box\Spout\Reader\ReaderFactory;
use Box\Spout\Common\Type; use Box\Spout\Common\Type;
use Box\Spout\Common\Helper\EncodingHelper; use Box\Spout\Common\Helper\EncodingHelper;
use Box\Spout\Reader\ReaderInterface;
use Box\Spout\TestUsingResource; use Box\Spout\TestUsingResource;
/** /**
@ -23,7 +28,7 @@ class ReaderTest extends \PHPUnit_Framework_TestCase
*/ */
public function testOpenShouldThrowExceptionIfFileDoesNotExist() public function testOpenShouldThrowExceptionIfFileDoesNotExist()
{ {
ReaderFactory::create(Type::CSV)->open('/path/to/fake/file.csv'); $this->createCSVReader()->open('/path/to/fake/file.csv');
} }
/** /**
@ -33,7 +38,7 @@ class ReaderTest extends \PHPUnit_Framework_TestCase
*/ */
public function testOpenShouldThrowExceptionIfTryingToReadBeforeOpeningReader() public function testOpenShouldThrowExceptionIfTryingToReadBeforeOpeningReader()
{ {
ReaderFactory::create(Type::CSV)->getSheetIterator(); $this->createCSVReader()->getSheetIterator();
} }
/** /**
@ -43,6 +48,7 @@ class ReaderTest extends \PHPUnit_Framework_TestCase
*/ */
public function testOpenShouldThrowExceptionIfFileNotReadable() public function testOpenShouldThrowExceptionIfFileNotReadable()
{ {
/** @var \Box\Spout\Common\Helper\GlobalFunctionsHelper|\PHPUnit_Framework_MockObject_MockObject $helperStub */
$helperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\GlobalFunctionsHelper') $helperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\GlobalFunctionsHelper')
->setMethods(['is_readable']) ->setMethods(['is_readable'])
->getMock(); ->getMock();
@ -50,8 +56,7 @@ class ReaderTest extends \PHPUnit_Framework_TestCase
$resourcePath = $this->getResourcePath('csv_standard.csv'); $resourcePath = $this->getResourcePath('csv_standard.csv');
$reader = ReaderFactory::create(Type::CSV); $reader = $this->createCSVReader(null, $helperStub);
$reader->setGlobalFunctionsHelper($helperStub);
$reader->open($resourcePath); $reader->open($resourcePath);
} }
@ -62,6 +67,7 @@ class ReaderTest extends \PHPUnit_Framework_TestCase
*/ */
public function testOpenShouldThrowExceptionIfCannotOpenFile() public function testOpenShouldThrowExceptionIfCannotOpenFile()
{ {
/** @var \Box\Spout\Common\Helper\GlobalFunctionsHelper|\PHPUnit_Framework_MockObject_MockObject $helperStub */
$helperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\GlobalFunctionsHelper') $helperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\GlobalFunctionsHelper')
->setMethods(['fopen']) ->setMethods(['fopen'])
->getMock(); ->getMock();
@ -69,8 +75,7 @@ class ReaderTest extends \PHPUnit_Framework_TestCase
$resourcePath = $this->getResourcePath('csv_standard.csv'); $resourcePath = $this->getResourcePath('csv_standard.csv');
$reader = ReaderFactory::create(Type::CSV); $reader = $this->createCSVReader(null, $helperStub);
$reader->setGlobalFunctionsHelper($helperStub);
$reader->open($resourcePath); $reader->open($resourcePath);
} }
@ -139,7 +144,7 @@ class ReaderTest extends \PHPUnit_Framework_TestCase
{ {
$allRows = $this->getAllRowsForFile( $allRows = $this->getAllRowsForFile(
'csv_with_multiple_empty_lines.csv', 'csv_with_multiple_empty_lines.csv',
',', '"', "\n", EncodingHelper::ENCODING_UTF8, ',', '"', EncodingHelper::ENCODING_UTF8,
$shouldPreserveEmptyRows = true $shouldPreserveEmptyRows = true
); );
@ -215,21 +220,6 @@ class ReaderTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('This is, a comma', $allRows[0][0]); $this->assertEquals('This is, a comma', $allRows[0][0]);
} }
/**
* @return void
*/
public function testReadCustomEOLs()
{
$allRows = $this->getAllRowsForFile('csv_with_CR_EOL.csv', ',', '"', "\r");
$expectedRows = [
['csv--11', 'csv--12', 'csv--13'],
['csv--21', 'csv--22', 'csv--23'],
['csv--31', 'csv--32', 'csv--33'],
];
$this->assertEquals($expectedRows, $allRows);
}
/** /**
* @return void * @return void
*/ */
@ -262,7 +252,7 @@ class ReaderTest extends \PHPUnit_Framework_TestCase
*/ */
public function testReadShouldSkipBom($fileName, $fileEncoding) public function testReadShouldSkipBom($fileName, $fileEncoding)
{ {
$allRows = $this->getAllRowsForFile($fileName, ',', '"', "\n", $fileEncoding); $allRows = $this->getAllRowsForFile($fileName, ',', '"', $fileEncoding);
$expectedRows = [ $expectedRows = [
['csv--11', 'csv--12', 'csv--13'], ['csv--11', 'csv--12', 'csv--13'],
@ -313,9 +303,8 @@ class ReaderTest extends \PHPUnit_Framework_TestCase
$helperStub->method('function_exists')->will($this->returnValueMap($returnValueMap)); $helperStub->method('function_exists')->will($this->returnValueMap($returnValueMap));
/** @var \Box\Spout\Reader\CSV\Reader $reader */ /** @var \Box\Spout\Reader\CSV\Reader $reader */
$reader = ReaderFactory::create(Type::CSV); $reader = $this->createCSVReader(null, $helperStub);
$reader $reader
->setGlobalFunctionsHelper($helperStub)
->setEncoding($fileEncoding) ->setEncoding($fileEncoding)
->open($resourcePath); ->open($resourcePath);
@ -343,7 +332,7 @@ class ReaderTest extends \PHPUnit_Framework_TestCase
$allRows = []; $allRows = [];
$resourcePath = $this->getResourcePath('csv_standard.csv'); $resourcePath = $this->getResourcePath('csv_standard.csv');
$reader = ReaderFactory::create(Type::CSV); $reader = $this->createCSVReader();
$reader->open($resourcePath); $reader->open($resourcePath);
foreach ($reader->getSheetIterator() as $sheet) { foreach ($reader->getSheetIterator() as $sheet) {
@ -428,47 +417,6 @@ class ReaderTest extends \PHPUnit_Framework_TestCase
$this->assertEquals($expectedRows, $allRows, 'Cell values should not be trimmed'); $this->assertEquals($expectedRows, $allRows, 'Cell values should not be trimmed');
} }
/**
* @param string $fileName
* @param string|void $fieldDelimiter
* @param string|void $fieldEnclosure
* @param string|void $endOfLineCharacter
* @param string|void $encoding
* @param bool|void $shouldPreserveEmptyRows
* @return array All the read rows the given file
*/
private function getAllRowsForFile(
$fileName,
$fieldDelimiter = ',',
$fieldEnclosure = '"',
$endOfLineCharacter = "\n",
$encoding = EncodingHelper::ENCODING_UTF8,
$shouldPreserveEmptyRows = false)
{
$allRows = [];
$resourcePath = $this->getResourcePath($fileName);
/** @var \Box\Spout\Reader\CSV\Reader $reader */
$reader = ReaderFactory::create(Type::CSV);
$reader
->setFieldDelimiter($fieldDelimiter)
->setFieldEnclosure($fieldEnclosure)
->setEndOfLineCharacter($endOfLineCharacter)
->setEncoding($encoding)
->setShouldPreserveEmptyRows($shouldPreserveEmptyRows)
->open($resourcePath);
foreach ($reader->getSheetIterator() as $sheetIndex => $sheet) {
foreach ($sheet->getRowIterator() as $rowIndex => $row) {
$allRows[] = $row;
}
}
$reader->close();
return $allRows;
}
/** /**
* @return void * @return void
*/ */
@ -481,7 +429,7 @@ class ReaderTest extends \PHPUnit_Framework_TestCase
stream_wrapper_register('spout', SpoutTestStream::CLASS_NAME); stream_wrapper_register('spout', SpoutTestStream::CLASS_NAME);
/** @var \Box\Spout\Reader\CSV\Reader $reader */ /** @var \Box\Spout\Reader\CSV\Reader $reader */
$reader = ReaderFactory::create(Type::CSV); $reader = $this->createCSVReader();
$reader->open($resourcePath); $reader->open($resourcePath);
foreach ($reader->getSheetIterator() as $sheet) { foreach ($reader->getSheetIterator() as $sheet) {
@ -511,8 +459,60 @@ class ReaderTest extends \PHPUnit_Framework_TestCase
public function testReadWithUnsupportedCustomStreamWrapper() public function testReadWithUnsupportedCustomStreamWrapper()
{ {
/** @var \Box\Spout\Reader\CSV\Reader $reader */ /** @var \Box\Spout\Reader\CSV\Reader $reader */
$reader = ReaderFactory::create(Type::CSV); $reader = $this->createCSVReader();
$reader->open('unsupported://foobar'); $reader->open('unsupported://foobar');
} }
/**
* @param \Box\Spout\Common\Helper\GlobalFunctionsHelper|null $optionsManager
* @param \Box\Spout\Common\Manager\OptionsManagerInterface|null $globalFunctionsHelper
* @return ReaderInterface
*/
private function createCSVReader($optionsManager = null, $globalFunctionsHelper = null)
{
$optionsManager = $optionsManager ?: new OptionsManager();
$globalFunctionsHelper = $globalFunctionsHelper ?: new GlobalFunctionsHelper();
$entityFactory = new EntityFactory(new HelperFactory());
return new Reader($optionsManager, $globalFunctionsHelper, $entityFactory);
}
/**
* @param string $fileName
* @param string|void $fieldDelimiter
* @param string|void $fieldEnclosure
* @param string|void $encoding
* @param bool|void $shouldPreserveEmptyRows
* @return array All the read rows the given file
*/
private function getAllRowsForFile(
$fileName,
$fieldDelimiter = ',',
$fieldEnclosure = '"',
$encoding = EncodingHelper::ENCODING_UTF8,
$shouldPreserveEmptyRows = false)
{
$allRows = [];
$resourcePath = $this->getResourcePath($fileName);
/** @var \Box\Spout\Reader\CSV\Reader $reader */
$reader = $this->createCSVReader();
$reader
->setFieldDelimiter($fieldDelimiter)
->setFieldEnclosure($fieldEnclosure)
->setEncoding($encoding)
->setShouldPreserveEmptyRows($shouldPreserveEmptyRows)
->open($resourcePath);
foreach ($reader->getSheetIterator() as $sheetIndex => $sheet) {
foreach ($sheet->getRowIterator() as $rowIndex => $row) {
$allRows[] = $row;
}
}
$reader->close();
return $allRows;
}
} }

View File

@ -1,6 +1,7 @@
<?php <?php
namespace Box\Spout\Reader\XLSX\Helper\SharedStringsCaching; namespace Box\Spout\Reader\XLSX\Helper\SharedStringsCaching;
use Box\Spout\Reader\XLSX\Creator\HelperFactory;
/** /**
* Class CachingStrategyFactoryTest * Class CachingStrategyFactoryTest
@ -12,7 +13,7 @@ class CachingStrategyFactoryTest extends \PHPUnit_Framework_TestCase
/** /**
* @return array * @return array
*/ */
public function dataProviderForTestGetBestCachingStrategy() public function dataProviderForTestCreateBestCachingStrategy()
{ {
return [ return [
[null, -1, 'FileBasedStrategy'], [null, -1, 'FileBasedStrategy'],
@ -26,14 +27,14 @@ class CachingStrategyFactoryTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* @dataProvider dataProviderForTestGetBestCachingStrategy * @dataProvider dataProviderForTestCreateBestCachingStrategy
* *
* @param int|null $sharedStringsUniqueCount * @param int|null $sharedStringsUniqueCount
* @param int $memoryLimitInKB * @param int $memoryLimitInKB
* @param string $expectedStrategyClassName * @param string $expectedStrategyClassName
* @return void * @return void
*/ */
public function testGetBestCachingStrategy($sharedStringsUniqueCount, $memoryLimitInKB, $expectedStrategyClassName) public function testCreateBestCachingStrategy($sharedStringsUniqueCount, $memoryLimitInKB, $expectedStrategyClassName)
{ {
/** @var CachingStrategyFactory|\PHPUnit_Framework_MockObject_MockObject $factoryStub */ /** @var CachingStrategyFactory|\PHPUnit_Framework_MockObject_MockObject $factoryStub */
$factoryStub = $this $factoryStub = $this
@ -44,15 +45,14 @@ class CachingStrategyFactoryTest extends \PHPUnit_Framework_TestCase
$factoryStub->method('getMemoryLimitInKB')->willReturn($memoryLimitInKB); $factoryStub->method('getMemoryLimitInKB')->willReturn($memoryLimitInKB);
\ReflectionHelper::setStaticValue('\Box\Spout\Reader\XLSX\Helper\SharedStringsCaching\CachingStrategyFactory', 'instance', $factoryStub); $tempFolder = sys_get_temp_dir();
$helperFactory = new HelperFactory($factoryStub);
$strategy = $factoryStub->getBestCachingStrategy($sharedStringsUniqueCount, null); $strategy = $factoryStub->createBestCachingStrategy($sharedStringsUniqueCount, $tempFolder, $helperFactory);
$fullExpectedStrategyClassName = 'Box\Spout\Reader\XLSX\Helper\SharedStringsCaching\\' . $expectedStrategyClassName; $fullExpectedStrategyClassName = 'Box\Spout\Reader\XLSX\Helper\SharedStringsCaching\\' . $expectedStrategyClassName;
$this->assertEquals($fullExpectedStrategyClassName, get_class($strategy)); $this->assertEquals($fullExpectedStrategyClassName, get_class($strategy));
$strategy->clearCache(); $strategy->clearCache();
\ReflectionHelper::reset();
} }
/** /**

View File

@ -2,6 +2,8 @@
namespace Box\Spout\Reader\XLSX\Helper; namespace Box\Spout\Reader\XLSX\Helper;
use Box\Spout\Reader\XLSX\Creator\EntityFactory;
use Box\Spout\Reader\XLSX\Creator\HelperFactory;
use Box\Spout\Reader\XLSX\Helper\SharedStringsCaching\CachingStrategyFactory; use Box\Spout\Reader\XLSX\Helper\SharedStringsCaching\CachingStrategyFactory;
use Box\Spout\Reader\XLSX\Helper\SharedStringsCaching\FileBasedStrategy; use Box\Spout\Reader\XLSX\Helper\SharedStringsCaching\FileBasedStrategy;
use Box\Spout\Reader\XLSX\Helper\SharedStringsCaching\InMemoryStrategy; use Box\Spout\Reader\XLSX\Helper\SharedStringsCaching\InMemoryStrategy;
@ -24,8 +26,7 @@ class SharedStringsHelperTest extends \PHPUnit_Framework_TestCase
*/ */
public function setUp() public function setUp()
{ {
$resourcePath = $this->getResourcePath('one_sheet_with_shared_strings.xlsx'); $this->sharedStringsHelper = null;
$this->sharedStringsHelper = new SharedStringsHelper($resourcePath);
} }
/** /**
@ -33,8 +34,27 @@ class SharedStringsHelperTest extends \PHPUnit_Framework_TestCase
*/ */
public function tearDown() public function tearDown()
{ {
if ($this->sharedStringsHelper !== null) {
$this->sharedStringsHelper->cleanup(); $this->sharedStringsHelper->cleanup();
} }
}
/**
* @param string $resourceName
* @return SharedStringsHelper
*/
private function createSharedStringsHelper($resourceName = 'one_sheet_with_shared_strings.xlsx')
{
$resourcePath = $this->getResourcePath($resourceName);
$tempFolder = sys_get_temp_dir();
$cachingStrategyFactory = new CachingStrategyFactory();
$helperFactory = new HelperFactory($cachingStrategyFactory);
$entityFactory = new EntityFactory($helperFactory);
$this->sharedStringsHelper = new SharedStringsHelper($resourcePath, $tempFolder, $entityFactory, $helperFactory, $cachingStrategyFactory);
return $this->sharedStringsHelper;
}
/** /**
* @expectedException \Box\Spout\Reader\Exception\SharedStringNotFoundException * @expectedException \Box\Spout\Reader\Exception\SharedStringNotFoundException
@ -42,8 +62,9 @@ class SharedStringsHelperTest extends \PHPUnit_Framework_TestCase
*/ */
public function testGetStringAtIndexShouldThrowExceptionIfStringNotFound() public function testGetStringAtIndexShouldThrowExceptionIfStringNotFound()
{ {
$this->sharedStringsHelper->extractSharedStrings(); $sharedStringsHelper = $this->createSharedStringsHelper();
$this->sharedStringsHelper->getStringAtIndex(PHP_INT_MAX); $sharedStringsHelper->extractSharedStrings();
$sharedStringsHelper->getStringAtIndex(PHP_INT_MAX);
} }
/** /**
@ -51,15 +72,16 @@ class SharedStringsHelperTest extends \PHPUnit_Framework_TestCase
*/ */
public function testGetStringAtIndexShouldReturnTheCorrectStringIfFound() public function testGetStringAtIndexShouldReturnTheCorrectStringIfFound()
{ {
$this->sharedStringsHelper->extractSharedStrings(); $sharedStringsHelper = $this->createSharedStringsHelper();
$sharedStringsHelper->extractSharedStrings();
$sharedString = $this->sharedStringsHelper->getStringAtIndex(0); $sharedString = $sharedStringsHelper->getStringAtIndex(0);
$this->assertEquals('s1--A1', $sharedString); $this->assertEquals('s1--A1', $sharedString);
$sharedString = $this->sharedStringsHelper->getStringAtIndex(24); $sharedString = $sharedStringsHelper->getStringAtIndex(24);
$this->assertEquals('s1--E5', $sharedString); $this->assertEquals('s1--E5', $sharedString);
$usedCachingStrategy = \ReflectionHelper::getValueOnObject($this->sharedStringsHelper, 'cachingStrategy'); $usedCachingStrategy = \ReflectionHelper::getValueOnObject($sharedStringsHelper, 'cachingStrategy');
$this->assertTrue($usedCachingStrategy instanceof InMemoryStrategy); $this->assertTrue($usedCachingStrategy instanceof InMemoryStrategy);
} }
@ -68,8 +90,7 @@ class SharedStringsHelperTest extends \PHPUnit_Framework_TestCase
*/ */
public function testGetStringAtIndexShouldWorkWithMultilineStrings() public function testGetStringAtIndexShouldWorkWithMultilineStrings()
{ {
$resourcePath = $this->getResourcePath('one_sheet_with_shared_multiline_strings.xlsx'); $sharedStringsHelper = $this->createSharedStringsHelper('one_sheet_with_shared_multiline_strings.xlsx');
$sharedStringsHelper = new SharedStringsHelper($resourcePath);
$sharedStringsHelper->extractSharedStrings(); $sharedStringsHelper->extractSharedStrings();
@ -78,8 +99,6 @@ class SharedStringsHelperTest extends \PHPUnit_Framework_TestCase
$sharedString = $sharedStringsHelper->getStringAtIndex(24); $sharedString = $sharedStringsHelper->getStringAtIndex(24);
$this->assertEquals("s1\nE5", $sharedString); $this->assertEquals("s1\nE5", $sharedString);
$sharedStringsHelper->cleanup();
} }
/** /**
@ -87,15 +106,12 @@ class SharedStringsHelperTest extends \PHPUnit_Framework_TestCase
*/ */
public function testGetStringAtIndexShouldWorkWithStringsContainingTextAndHyperlinkInSameCell() public function testGetStringAtIndexShouldWorkWithStringsContainingTextAndHyperlinkInSameCell()
{ {
$resourcePath = $this->getResourcePath('one_sheet_with_shared_strings_containing_text_and_hyperlink_in_same_cell.xlsx'); $sharedStringsHelper = $this->createSharedStringsHelper('one_sheet_with_shared_strings_containing_text_and_hyperlink_in_same_cell.xlsx');
$sharedStringsHelper = new SharedStringsHelper($resourcePath);
$sharedStringsHelper->extractSharedStrings(); $sharedStringsHelper->extractSharedStrings();
$sharedString = $sharedStringsHelper->getStringAtIndex(0); $sharedString = $sharedStringsHelper->getStringAtIndex(0);
$this->assertEquals('go to https://github.com please', $sharedString); $this->assertEquals('go to https://github.com please', $sharedString);
$sharedStringsHelper->cleanup();
} }
/** /**
@ -103,15 +119,12 @@ class SharedStringsHelperTest extends \PHPUnit_Framework_TestCase
*/ */
public function testGetStringAtIndexShouldNotDoubleDecodeHTMLEntities() public function testGetStringAtIndexShouldNotDoubleDecodeHTMLEntities()
{ {
$resourcePath = $this->getResourcePath('one_sheet_with_pre_encoded_html_entities.xlsx'); $sharedStringsHelper = $this->createSharedStringsHelper('one_sheet_with_pre_encoded_html_entities.xlsx');
$sharedStringsHelper = new SharedStringsHelper($resourcePath);
$sharedStringsHelper->extractSharedStrings(); $sharedStringsHelper->extractSharedStrings();
$sharedString = $sharedStringsHelper->getStringAtIndex(0); $sharedString = $sharedStringsHelper->getStringAtIndex(0);
$this->assertEquals('quote: &#34; - ampersand: &amp;', $sharedString); $this->assertEquals('quote: &#34; - ampersand: &amp;', $sharedString);
$sharedStringsHelper->cleanup();
} }
/** /**
@ -123,8 +136,7 @@ class SharedStringsHelperTest extends \PHPUnit_Framework_TestCase
$originalMemoryLimit = ini_get('memory_limit'); $originalMemoryLimit = ini_get('memory_limit');
ini_set('memory_limit', '-1'); ini_set('memory_limit', '-1');
$resourcePath = $this->getResourcePath('sheet_with_lots_of_shared_strings.xlsx'); $sharedStringsHelper = $this->createSharedStringsHelper('sheet_with_lots_of_shared_strings.xlsx');
$sharedStringsHelper = new SharedStringsHelper($resourcePath);
$sharedStringsHelper->extractSharedStrings(); $sharedStringsHelper->extractSharedStrings();
@ -137,8 +149,6 @@ class SharedStringsHelperTest extends \PHPUnit_Framework_TestCase
$usedCachingStrategy = \ReflectionHelper::getValueOnObject($sharedStringsHelper, 'cachingStrategy'); $usedCachingStrategy = \ReflectionHelper::getValueOnObject($sharedStringsHelper, 'cachingStrategy');
$this->assertTrue($usedCachingStrategy instanceof FileBasedStrategy); $this->assertTrue($usedCachingStrategy instanceof FileBasedStrategy);
$sharedStringsHelper->cleanup();
ini_set('memory_limit', $originalMemoryLimit); ini_set('memory_limit', $originalMemoryLimit);
} }
} }

View File

@ -1,6 +1,9 @@
<?php <?php
namespace Box\Spout\Reader\XLSX\Helper; namespace Box\Spout\Reader\XLSX\Helper;
use Box\Spout\Reader\XLSX\Creator\EntityFactory;
use Box\Spout\Reader\XLSX\Creator\HelperFactory;
use Box\Spout\Reader\XLSX\Helper\SharedStringsCaching\CachingStrategyFactory;
/** /**
* Class StyleManagerTest * Class StyleManagerTest
@ -17,9 +20,11 @@ class StyleHelperTest extends \PHPUnit_Framework_TestCase
*/ */
private function getStyleHelperMock($styleAttributes = [], $customNumberFormats = []) private function getStyleHelperMock($styleAttributes = [], $customNumberFormats = [])
{ {
$entityFactory = new EntityFactory(new HelperFactory(new CachingStrategyFactory()));
/** @var StyleHelper $styleHelper */ /** @var StyleHelper $styleHelper */
$styleHelper = $this->getMockBuilder('\Box\Spout\Reader\XLSX\Helper\StyleHelper') $styleHelper = $this->getMockBuilder('\Box\Spout\Reader\XLSX\Helper\StyleHelper')
->setConstructorArgs(['/path/to/file.xlsx']) ->setConstructorArgs(['/path/to/file.xlsx', $entityFactory])
->setMethods(['getCustomNumberFormats', 'getStylesAttributes']) ->setMethods(['getCustomNumberFormats', 'getStylesAttributes'])
->getMock(); ->getMock();