Refactor readers for better di (#457)

* 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).

* Escapers should not be singletons

Instead, they should be proper object that can be injected where needed.
This commit is contained in:
Adrien Loison authored and GitHub committed 2017-08-27 00:01:17 +02:00
1 parent 4d6437fa77
commit b7e46740ce
66 files changed
+1095 -618

No files matched your search

@@ -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);
}
}
@@ -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);
}
}
+12 -33
View File
@@ -2,7 +2,9 @@
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;
/**
@@ -11,7 +13,7 @@ use Box\Spout\Common\Exception\IOException;
*
* @package Box\Spout\Reader\CSV
*/
class Reader extends AbstractReader
class Reader extends ReaderAbstract
{
/** @var resource Pointer to the file to be written */
protected $filePointer;
@@ -22,19 +24,6 @@ class Reader extends AbstractReader
/** @var string Original value for the "auto_detect_line_endings" INI value */
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.
* Needs to be called before opening the reader.
@@ -44,7 +33,7 @@ class Reader extends AbstractReader
*/
public function setFieldDelimiter($fieldDelimiter)
{
$this->getOptions()->setFieldDelimiter($fieldDelimiter);
$this->optionsManager->setOption(Options::FIELD_DELIMITER, $fieldDelimiter);
return $this;
}
@@ -57,7 +46,7 @@ class Reader extends AbstractReader
*/
public function setFieldEnclosure($fieldEnclosure)
{
$this->getOptions()->setFieldEnclosure($fieldEnclosure);
$this->optionsManager->setOption(Options::FIELD_ENCLOSURE, $fieldEnclosure);
return $this;
}
@@ -70,20 +59,7 @@ class Reader extends AbstractReader
*/
public function setEncoding($encoding)
{
$this->getOptions()->setEncoding($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);
$this->optionsManager->setOption(Options::ENCODING, $encoding);
return $this;
}
@@ -115,9 +91,12 @@ class Reader extends AbstractReader
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->getOptions(),
$this->optionsManager,
$this->globalFunctionsHelper
);
}
-110
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;
}
}
+11 -30
View File
@@ -2,6 +2,9 @@
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\Common\Helper\EncodingHelper;
@@ -39,9 +42,6 @@ class RowIterator implements IteratorInterface
/** @var string Encoding of the CSV file to be read */
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 */
protected $shouldPreserveEmptyRows;
@@ -51,25 +51,21 @@ class RowIterator implements IteratorInterface
/** @var \Box\Spout\Common\Helper\EncodingHelper Helper to work with different encodings */
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 \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
*/
public function __construct($filePointer, $options, $globalFunctionsHelper)
public function __construct($filePointer, $optionsManager, $encodingHelper, $globalFunctionsHelper)
{
$this->filePointer = $filePointer;
$this->fieldDelimiter = $options->getFieldDelimiter();
$this->fieldEnclosure = $options->getFieldEnclosure();
$this->encoding = $options->getEncoding();
$this->inputEOLDelimiter = $options->getEndOfLineCharacter();
$this->shouldPreserveEmptyRows = $options->shouldPreserveEmptyRows();
$this->fieldDelimiter = $optionsManager->getOption(Options::FIELD_DELIMITER);
$this->fieldEnclosure = $optionsManager->getOption(Options::FIELD_ENCLOSURE);
$this->encoding = $optionsManager->getOption(Options::ENCODING);
$this->shouldPreserveEmptyRows = $optionsManager->getOption(Options::SHOULD_PRESERVE_EMPTY_ROWS);
$this->encodingHelper = $encodingHelper;
$this->globalFunctionsHelper = $globalFunctionsHelper;
$this->encodingHelper = new EncodingHelper($globalFunctionsHelper);
}
/**
@@ -202,21 +198,6 @@ class RowIterator implements IteratorInterface
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
* @return bool Whether the given line is empty
+5 -3
View File
@@ -2,6 +2,7 @@
namespace Box\Spout\Reader\CSV;
use Box\Spout\Reader\CSV\Creator\EntityFactory;
use Box\Spout\Reader\SheetInterface;
/**
@@ -16,12 +17,13 @@ class Sheet implements SheetInterface
/**
* @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 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);
}
/**
+5 -3
View File
@@ -2,6 +2,7 @@
namespace Box\Spout\Reader\CSV;
use Box\Spout\Reader\CSV\Creator\EntityFactory;
use Box\Spout\Reader\IteratorInterface;
/**
@@ -20,12 +21,13 @@ class SheetIterator implements IteratorInterface
/**
* @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 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);
}
/**