diff --git a/src/Spout/Common/Creator/HelperFactory.php b/src/Spout/Common/Creator/HelperFactory.php new file mode 100644 index 0000000..9b5c793 --- /dev/null +++ b/src/Spout/Common/Creator/HelperFactory.php @@ -0,0 +1,42 @@ +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); + } +} diff --git a/src/Spout/Reader/CSV/Manager/OptionsManager.php b/src/Spout/Reader/CSV/Manager/OptionsManager.php new file mode 100644 index 0000000..267ff77 --- /dev/null +++ b/src/Spout/Reader/CSV/Manager/OptionsManager.php @@ -0,0 +1,42 @@ +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); + } +} diff --git a/src/Spout/Reader/CSV/Reader.php b/src/Spout/Reader/CSV/Reader.php index 648a12d..89a3cf1 100644 --- a/src/Spout/Reader/CSV/Reader.php +++ b/src/Spout/Reader/CSV/Reader.php @@ -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 ); } diff --git a/src/Spout/Reader/CSV/ReaderOptions.php b/src/Spout/Reader/CSV/ReaderOptions.php deleted file mode 100644 index 9a1adb8..0000000 --- a/src/Spout/Reader/CSV/ReaderOptions.php +++ /dev/null @@ -1,110 +0,0 @@ -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; - } -} diff --git a/src/Spout/Reader/CSV/RowIterator.php b/src/Spout/Reader/CSV/RowIterator.php index a2a6672..390b3d4 100644 --- a/src/Spout/Reader/CSV/RowIterator.php +++ b/src/Spout/Reader/CSV/RowIterator.php @@ -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 diff --git a/src/Spout/Reader/CSV/Sheet.php b/src/Spout/Reader/CSV/Sheet.php index 9a688db..e59a7e2 100644 --- a/src/Spout/Reader/CSV/Sheet.php +++ b/src/Spout/Reader/CSV/Sheet.php @@ -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); } /** diff --git a/src/Spout/Reader/CSV/SheetIterator.php b/src/Spout/Reader/CSV/SheetIterator.php index 58a9480..e1b2d93 100644 --- a/src/Spout/Reader/CSV/SheetIterator.php +++ b/src/Spout/Reader/CSV/SheetIterator.php @@ -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); } /** diff --git a/src/Spout/Reader/Common/Creator/EntityFactoryInterface.php b/src/Spout/Reader/Common/Creator/EntityFactoryInterface.php new file mode 100644 index 0000000..184a72c --- /dev/null +++ b/src/Spout/Reader/Common/Creator/EntityFactoryInterface.php @@ -0,0 +1,12 @@ +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(); + } +} diff --git a/src/Spout/Reader/ODS/Creator/HelperFactory.php b/src/Spout/Reader/ODS/Creator/HelperFactory.php new file mode 100644 index 0000000..cebd732 --- /dev/null +++ b/src/Spout/Reader/ODS/Creator/HelperFactory.php @@ -0,0 +1,33 @@ +setOption(Options::SHOULD_FORMAT_DATES, false); + $this->setOption(Options::SHOULD_PRESERVE_EMPTY_ROWS, false); + } +} diff --git a/src/Spout/Reader/ODS/Reader.php b/src/Spout/Reader/ODS/Reader.php index dbdc47b..0d85c6c 100644 --- a/src/Spout/Reader/ODS/Reader.php +++ b/src/Spout/Reader/ODS/Reader.php @@ -3,7 +3,8 @@ namespace Box\Spout\Reader\ODS; 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 @@ -11,7 +12,7 @@ use Box\Spout\Reader\AbstractReader; * * @package Box\Spout\Reader\ODS */ -class Reader extends AbstractReader +class Reader extends ReaderAbstract { /** @var \ZipArchive */ protected $zip; @@ -19,19 +20,6 @@ class Reader extends AbstractReader /** @var SheetIterator To iterator over the ODS sheets */ 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 * @@ -52,10 +40,15 @@ class Reader extends AbstractReader */ protected function openReader($filePath) { - $this->zip = new \ZipArchive(); + /** @var EntityFactory $entityFactory */ + $entityFactory = $this->entityFactory; + + $this->zip = $entityFactory->createZipArchive(); 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 { throw new IOException("Could not open $filePath for reading."); } diff --git a/src/Spout/Reader/ODS/ReaderOptions.php b/src/Spout/Reader/ODS/ReaderOptions.php deleted file mode 100644 index 2d29640..0000000 --- a/src/Spout/Reader/ODS/ReaderOptions.php +++ /dev/null @@ -1,14 +0,0 @@ -" 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->shouldPreserveEmptyRows = $options->shouldPreserveEmptyRows(); - $this->cellValueFormatter = new CellValueFormatter($options->shouldFormatDates()); + $this->shouldPreserveEmptyRows = $optionsManager->getOption(Options::SHOULD_PRESERVE_EMPTY_ROWS); + $this->cellValueFormatter = $helperFactory->createCellValueFormatter($optionsManager->getOption(Options::SHOULD_FORMAT_DATES)); // 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_CELL, XMLProcessor::NODE_TYPE_START, [$this, 'processCellStartingNode']); $this->xmlProcessor->registerCallback(self::XML_NODE_ROW, XMLProcessor::NODE_TYPE_END, [$this, 'processRowEndingNode']); diff --git a/src/Spout/Reader/ODS/Sheet.php b/src/Spout/Reader/ODS/Sheet.php index 794ad3a..7af1be8 100644 --- a/src/Spout/Reader/ODS/Sheet.php +++ b/src/Spout/Reader/ODS/Sheet.php @@ -2,6 +2,7 @@ namespace Box\Spout\Reader\ODS; +use Box\Spout\Reader\ODS\Creator\EntityFactory; use Box\Spout\Reader\SheetInterface; 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 string $sheetName Name of the sheet * @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->name = $sheetName; $this->isActive = $isSheetActive; diff --git a/src/Spout/Reader/ODS/SheetIterator.php b/src/Spout/Reader/ODS/SheetIterator.php index 995c136..6d2f69a 100644 --- a/src/Spout/Reader/ODS/SheetIterator.php +++ b/src/Spout/Reader/ODS/SheetIterator.php @@ -5,6 +5,8 @@ namespace Box\Spout\Reader\ODS; use Box\Spout\Common\Exception\IOException; use Box\Spout\Reader\Exception\XMLProcessingException; 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\Wrapper\XMLReader; @@ -25,8 +27,11 @@ class SheetIterator implements IteratorInterface /** @var string $filePath Path of the file to be read */ protected $filePath; - /** @var \Box\Spout\Reader\ODS\ReaderOptions Reader's current options */ - protected $options; + /** @var \Box\Spout\Common\Manager\OptionsManagerInterface Reader's options manager */ + protected $optionsManager; + + /** @var EntityFactory $entityFactory Factory to create entities */ + protected $entityFactory; /** @var XMLReader The XMLReader object that will help read sheet's XML data */ protected $xmlReader; @@ -45,19 +50,21 @@ class SheetIterator implements IteratorInterface /** * @param string $filePath Path of the file to be read - * @param \Box\Spout\Reader\ODS\ReaderOptions $options Reader's current options - * @throws \Box\Spout\Reader\Exception\NoSheetsFoundException If there are no sheets in the file + * @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager + * @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->options = $options; - $this->xmlReader = new XMLReader(); + $this->optionsManager = $optionsManager; + $this->entityFactory = $entityFactory; + $this->xmlReader = $entityFactory->createXMLReader(); /** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */ $this->escaper = \Box\Spout\Common\Escaper\ODS::getInstance(); - $settingsHelper = new SettingsHelper(); + $settingsHelper = $helperFactory->createSettingsHelper(); $this->activeSheetName = $settingsHelper->getActiveSheetName($filePath); } @@ -124,7 +131,7 @@ class SheetIterator implements IteratorInterface $sheetName = $this->escaper->unescape($escapedSheetName); $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); } /** diff --git a/src/Spout/Reader/AbstractReader.php b/src/Spout/Reader/ReaderAbstract.php similarity index 83% rename from src/Spout/Reader/AbstractReader.php rename to src/Spout/Reader/ReaderAbstract.php index 880efbd..4de55a1 100644 --- a/src/Spout/Reader/AbstractReader.php +++ b/src/Spout/Reader/ReaderAbstract.php @@ -3,31 +3,31 @@ namespace Box\Spout\Reader; 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; /** - * Class AbstractReader + * Class ReaderAbstract * * @package Box\Spout\Reader * @abstract */ -abstract class AbstractReader implements ReaderInterface +abstract class ReaderAbstract implements ReaderInterface { /** @var bool Indicates whether the stream is currently open */ protected $isStreamOpened = false; + /** @var EntityFactoryInterface Factory to create entities */ + protected $entityFactory; + /** @var \Box\Spout\Common\Helper\GlobalFunctionsHelper Helper to work with global functions */ protected $globalFunctionsHelper; - /** @var \Box\Spout\Reader\Common\ReaderOptions Reader's customized options */ - protected $options; - - /** - * Returns the reader's current options - * - * @return \Box\Spout\Reader\Common\ReaderOptions - */ - abstract protected function getOptions(); + /** @var OptionsManagerInterface Writer options manager */ + protected $optionsManager; /** * Returns whether stream wrappers are supported @@ -47,25 +47,30 @@ abstract class AbstractReader implements ReaderInterface /** * Returns an iterator to iterate over sheets. * - * @return \Iterator To iterate over sheets + * @return IteratorInterface To iterate over sheets */ abstract protected function getConcreteSheetIterator(); /** * Closes the reader. To be used after reading the file. * - * @return AbstractReader + * @return ReaderAbstract */ abstract protected function closeReader(); /** - * @param \Box\Spout\Common\Helper\GlobalFunctionsHelper $globalFunctionsHelper - * @return AbstractReader + * @param OptionsManagerInterface $optionsManager + * @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; - return $this; + $this->entityFactory = $entityFactory; } /** @@ -73,11 +78,11 @@ abstract class AbstractReader implements ReaderInterface * * @api * @param bool $shouldFormatDates - * @return AbstractReader + * @return ReaderAbstract */ public function setShouldFormatDates($shouldFormatDates) { - $this->getOptions()->setShouldFormatDates($shouldFormatDates); + $this->optionsManager->setOption(Options::SHOULD_FORMAT_DATES, $shouldFormatDates); return $this; } @@ -86,11 +91,11 @@ abstract class AbstractReader implements ReaderInterface * * @api * @param bool $shouldPreserveEmptyRows - * @return AbstractReader + * @return ReaderAbstract */ public function setShouldPreserveEmptyRows($shouldPreserveEmptyRows) { - $this->getOptions()->setShouldPreserveEmptyRows($shouldPreserveEmptyRows); + $this->optionsManager->setOption(Options::SHOULD_PRESERVE_EMPTY_ROWS, $shouldPreserveEmptyRows); return $this; } diff --git a/src/Spout/Reader/ReaderFactory.php b/src/Spout/Reader/ReaderFactory.php index 93a52cb..39e6516 100644 --- a/src/Spout/Reader/ReaderFactory.php +++ b/src/Spout/Reader/ReaderFactory.php @@ -2,9 +2,11 @@ namespace Box\Spout\Reader; +use Box\Spout\Common\Creator\HelperFactory; use Box\Spout\Common\Exception\UnsupportedTypeException; use Box\Spout\Common\Helper\GlobalFunctionsHelper; use Box\Spout\Common\Type; +use Box\Spout\Reader\XLSX\Helper\SharedStringsCaching\CachingStrategyFactory; /** * Class ReaderFactory @@ -25,24 +27,53 @@ class ReaderFactory */ public static function create($readerType) { - $reader = null; switch ($readerType) { - case Type::CSV: - $reader = new CSV\Reader(); - break; - case Type::XLSX: - $reader = new XLSX\Reader(); - break; - case Type::ODS: - $reader = new ODS\Reader(); - break; + case Type::CSV: return self::getCSVReader(); + case Type::XLSX: return self::getXLSXReader(); + case Type::ODS: return self::getODSReader(); default: 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); } } diff --git a/src/Spout/Reader/SheetInterface.php b/src/Spout/Reader/SheetInterface.php index bc19078..4f3eea0 100644 --- a/src/Spout/Reader/SheetInterface.php +++ b/src/Spout/Reader/SheetInterface.php @@ -12,7 +12,7 @@ interface SheetInterface /** * Returns an iterator to iterate over the sheet's rows. * - * @return \Iterator + * @return IteratorInterface */ public function getRowIterator(); } diff --git a/src/Spout/Reader/Wrapper/XMLReader.php b/src/Spout/Reader/Wrapper/XMLReader.php index 2e20327..ffe6818 100644 --- a/src/Spout/Reader/Wrapper/XMLReader.php +++ b/src/Spout/Reader/Wrapper/XMLReader.php @@ -1,7 +1,6 @@ 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); + } +} diff --git a/src/Spout/Reader/XLSX/Creator/HelperFactory.php b/src/Spout/Reader/XLSX/Creator/HelperFactory.php new file mode 100644 index 0000000..9b70d63 --- /dev/null +++ b/src/Spout/Reader/XLSX/Creator/HelperFactory.php @@ -0,0 +1,75 @@ +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); + } +} diff --git a/src/Spout/Reader/XLSX/Helper/SharedStringsCaching/CachingStrategyFactory.php b/src/Spout/Reader/XLSX/Helper/SharedStringsCaching/CachingStrategyFactory.php index 36e0bfe..7ba55e5 100644 --- a/src/Spout/Reader/XLSX/Helper/SharedStringsCaching/CachingStrategyFactory.php +++ b/src/Spout/Reader/XLSX/Helper/SharedStringsCaching/CachingStrategyFactory.php @@ -1,6 +1,7 @@ isInMemoryStrategyUsageSafe($sharedStringsUniqueCount)) { return new InMemoryStrategy($sharedStringsUniqueCount); } else { - return new FileBasedStrategy($tempFolder, self::MAX_NUM_STRINGS_PER_TEMP_FILE); + return new FileBasedStrategy($tempFolder, self::MAX_NUM_STRINGS_PER_TEMP_FILE, $helperFactory); } } diff --git a/src/Spout/Reader/XLSX/Helper/SharedStringsCaching/FileBasedStrategy.php b/src/Spout/Reader/XLSX/Helper/SharedStringsCaching/FileBasedStrategy.php index b4e699f..b6c866b 100644 --- a/src/Spout/Reader/XLSX/Helper/SharedStringsCaching/FileBasedStrategy.php +++ b/src/Spout/Reader/XLSX/Helper/SharedStringsCaching/FileBasedStrategy.php @@ -5,6 +5,7 @@ namespace Box\Spout\Reader\XLSX\Helper\SharedStringsCaching; use Box\Spout\Common\Helper\FileSystemHelper; use Box\Spout\Common\Helper\GlobalFunctionsHelper; use Box\Spout\Reader\Exception\SharedStringNotFoundException; +use Box\Spout\Reader\XLSX\Creator\HelperFactory; /** * Class FileBasedStrategy @@ -51,18 +52,18 @@ class FileBasedStrategy implements CachingStrategyInterface 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 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 = new FileSystemHelper($rootTempFolder); - $this->tempFolder = $this->fileSystemHelper->createFolder($rootTempFolder, uniqid('sharedstrings')); + $this->fileSystemHelper = $helperFactory->createFileSystemHelper($tempFolder); + $this->tempFolder = $this->fileSystemHelper->createFolder($tempFolder, uniqid('sharedstrings')); $this->maxNumStringsPerTempFile = $maxNumStringsPerTempFile; - $this->globalFunctionsHelper = new GlobalFunctionsHelper(); + $this->globalFunctionsHelper = $helperFactory->createGlobalFunctionsHelper(); $this->tempFilePointer = null; } diff --git a/src/Spout/Reader/XLSX/Helper/SharedStringsHelper.php b/src/Spout/Reader/XLSX/Helper/SharedStringsHelper.php index 415d5cf..cb5188a 100644 --- a/src/Spout/Reader/XLSX/Helper/SharedStringsHelper.php +++ b/src/Spout/Reader/XLSX/Helper/SharedStringsHelper.php @@ -5,6 +5,8 @@ namespace Box\Spout\Reader\XLSX\Helper; use Box\Spout\Common\Exception\IOException; use Box\Spout\Reader\Exception\XMLProcessingException; 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\CachingStrategyInterface; @@ -40,17 +42,32 @@ class SharedStringsHelper /** @var string Temporary folder where the temporary files to store shared strings will be stored */ 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 */ protected $cachingStrategy; /** * @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->tempFolder = $tempFolder; + $this->entityFactory = $entityFactory; + $this->helperFactory = $helperFactory; + $this->cachingStrategyFactory = $cachingStrategyFactory; } /** @@ -61,7 +78,7 @@ class SharedStringsHelper public function hasSharedStrings() { $hasSharedStrings = false; - $zip = new \ZipArchive(); + $zip = $this->entityFactory->createZipArchive(); if ($zip->open($this->filePath) === true) { $hasSharedStrings = ($zip->locateName(self::SHARED_STRINGS_XML_FILE_PATH) !== false); @@ -86,7 +103,7 @@ class SharedStringsHelper */ public function extractSharedStrings() { - $xmlReader = new XMLReader(); + $xmlReader = $this->entityFactory->createXMLReader(); $sharedStringIndex = 0; if ($xmlReader->openFileInZip($this->filePath, self::SHARED_STRINGS_XML_FILE_PATH) === false) { @@ -151,8 +168,8 @@ class SharedStringsHelper */ protected function getBestSharedStringsCachingStrategy($sharedStringsUniqueCount) { - return CachingStrategyFactory::getInstance() - ->getBestCachingStrategy($sharedStringsUniqueCount, $this->tempFolder); + return $this->cachingStrategyFactory + ->createBestCachingStrategy($sharedStringsUniqueCount, $this->tempFolder, $this->helperFactory); } /** diff --git a/src/Spout/Reader/XLSX/Helper/SheetHelper.php b/src/Spout/Reader/XLSX/Helper/SheetHelper.php index b74ba01..8b6af6c 100644 --- a/src/Spout/Reader/XLSX/Helper/SheetHelper.php +++ b/src/Spout/Reader/XLSX/Helper/SheetHelper.php @@ -3,6 +3,7 @@ namespace Box\Spout\Reader\XLSX\Helper; use Box\Spout\Reader\Wrapper\XMLReader; +use Box\Spout\Reader\XLSX\Creator\EntityFactory; use Box\Spout\Reader\XLSX\Sheet; /** @@ -33,8 +34,8 @@ class SheetHelper /** @var string Path of the XLSX file being read */ protected $filePath; - /** @var \Box\Spout\Reader\XLSX\ReaderOptions Reader's current options */ - protected $options; + /** @var \Box\Spout\Common\Manager\OptionsManagerInterface Reader's options manager */ + protected $optionsManager; /** @var \Box\Spout\Reader\XLSX\Helper\SharedStringsHelper Helper to work with shared strings */ protected $sharedStringsHelper; @@ -42,18 +43,23 @@ class SheetHelper /** @var \Box\Spout\Common\Helper\GlobalFunctionsHelper Helper to work with global functions */ protected $globalFunctionsHelper; + /** @var EntityFactory Factory to create entities */ + protected $entityFactory; + /** * @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\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->options = $options; + $this->optionsManager = $optionsManager; $this->sharedStringsHelper = $sharedStringsHelper; $this->globalFunctionsHelper = $globalFunctionsHelper; + $this->entityFactory = $entityFactory; } /** @@ -68,7 +74,8 @@ class SheetHelper $sheetIndex = 0; $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)) { while ($xmlReader->read()) { if ($xmlReader->isPositionedOnStartingNode(self::XML_NODE_WORKBOOK_VIEW)) { @@ -112,10 +119,14 @@ class SheetHelper $sheetDataXMLFilePath = $this->getSheetDataXMLFilePathForSheetId($sheetId); - return new Sheet( - $this->filePath, $sheetDataXMLFilePath, - $sheetIndexZeroBased, $sheetName, $isSheetActive, - $this->options, $this->sharedStringsHelper + return $this->entityFactory->createSheet( + $this->filePath, + $sheetDataXMLFilePath, + $sheetIndexZeroBased, + $sheetName, + $isSheetActive, + $this->optionsManager, + $this->sharedStringsHelper ); } @@ -128,7 +139,7 @@ class SheetHelper $sheetDataXMLFilePath = ''; // 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)) { while ($xmlReader->read()) { if ($xmlReader->isPositionedOnStartingNode(self::XML_NODE_RELATIONSHIP)) { diff --git a/src/Spout/Reader/XLSX/Helper/StyleHelper.php b/src/Spout/Reader/XLSX/Helper/StyleHelper.php index 000adab..2781577 100644 --- a/src/Spout/Reader/XLSX/Helper/StyleHelper.php +++ b/src/Spout/Reader/XLSX/Helper/StyleHelper.php @@ -2,7 +2,7 @@ namespace Box\Spout\Reader\XLSX\Helper; -use Box\Spout\Reader\Wrapper\XMLReader; +use Box\Spout\Reader\XLSX\Creator\EntityFactory; /** * Class StyleHelper @@ -53,6 +53,9 @@ class StyleHelper /** @var string Path of the XLSX file being read */ protected $filePath; + /** @var EntityFactory Factory to create entities */ + protected $entityFactory; + /** @var array Array containing the IDs of built-in number formats indicating a date */ protected $builtinNumFmtIdIndicatingDates; @@ -67,10 +70,12 @@ class StyleHelper /** * @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->entityFactory = $entityFactory; $this->builtinNumFmtIdIndicatingDates = array_keys(self::$builtinNumFmtIdToNumFormatMapping); } @@ -107,7 +112,7 @@ class StyleHelper $this->customNumberFormats = []; $this->stylesAttributes = []; - $xmlReader = new XMLReader(); + $xmlReader = $this->entityFactory->createXMLReader(); if ($xmlReader->openFileInZip($this->filePath, self::STYLES_XML_FILE_PATH)) { while ($xmlReader->read()) { diff --git a/src/Spout/Reader/XLSX/Manager/OptionsManager.php b/src/Spout/Reader/XLSX/Manager/OptionsManager.php new file mode 100644 index 0000000..f56d0ec --- /dev/null +++ b/src/Spout/Reader/XLSX/Manager/OptionsManager.php @@ -0,0 +1,37 @@ +setOption(Options::TEMP_FOLDER, sys_get_temp_dir()); + $this->setOption(Options::SHOULD_FORMAT_DATES, false); + $this->setOption(Options::SHOULD_PRESERVE_EMPTY_ROWS, false); + } +} diff --git a/src/Spout/Reader/XLSX/Reader.php b/src/Spout/Reader/XLSX/Reader.php index 76e8e32..6881e3f 100644 --- a/src/Spout/Reader/XLSX/Reader.php +++ b/src/Spout/Reader/XLSX/Reader.php @@ -3,8 +3,13 @@ namespace Box\Spout\Reader\XLSX; use Box\Spout\Common\Exception\IOException; -use Box\Spout\Reader\AbstractReader; -use Box\Spout\Reader\XLSX\Helper\SharedStringsHelper; +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\ReaderAbstract; +use Box\Spout\Reader\XLSX\Creator\EntityFactory; +use Box\Spout\Reader\XLSX\Creator\HelperFactory; /** * Class Reader @@ -12,8 +17,11 @@ use Box\Spout\Reader\XLSX\Helper\SharedStringsHelper; * * @package Box\Spout\Reader\XLSX */ -class Reader extends AbstractReader +class Reader extends ReaderAbstract { + /** @var HelperFactory */ + protected $helperFactory; + /** @var \ZipArchive */ protected $zip; @@ -25,16 +33,19 @@ class Reader extends AbstractReader /** - * Returns the reader's current options - * - * @return ReaderOptions + * @param OptionsManagerInterface $optionsManager + * @param GlobalFunctionsHelper $globalFunctionsHelper + * @param EntityFactoryInterface $entityFactory + * @param HelperFactory $helperFactory */ - protected function getOptions() + public function __construct( + OptionsManagerInterface $optionsManager, + GlobalFunctionsHelper $globalFunctionsHelper, + EntityFactoryInterface $entityFactory, + HelperFactory $helperFactory) { - if (!isset($this->options)) { - $this->options = new ReaderOptions(); - } - return $this->options; + parent::__construct($optionsManager, $globalFunctionsHelper, $entityFactory); + $this->helperFactory = $helperFactory; } /** @@ -43,7 +54,7 @@ class Reader extends AbstractReader */ public function setTempFolder($tempFolder) { - $this->getOptions()->setTempFolder($tempFolder); + $this->optionsManager->setOption(Options::TEMP_FOLDER, $tempFolder); return $this; } @@ -69,17 +80,21 @@ class Reader extends AbstractReader */ protected function openReader($filePath) { - $this->zip = new \ZipArchive(); + /** @var EntityFactory $entityFactory */ + $entityFactory = $this->entityFactory; + + $this->zip = $entityFactory->createZipArchive(); 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()) { // Extracts all the strings from the sheets for easy access in the future $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 { throw new IOException("Could not open $filePath for reading."); } diff --git a/src/Spout/Reader/XLSX/ReaderOptions.php b/src/Spout/Reader/XLSX/ReaderOptions.php deleted file mode 100644 index 5f78c5d..0000000 --- a/src/Spout/Reader/XLSX/ReaderOptions.php +++ /dev/null @@ -1,33 +0,0 @@ -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; - } -} diff --git a/src/Spout/Reader/XLSX/RowIterator.php b/src/Spout/Reader/XLSX/RowIterator.php index 45069b3..1bda0d0 100644 --- a/src/Spout/Reader/XLSX/RowIterator.php +++ b/src/Spout/Reader/XLSX/RowIterator.php @@ -3,9 +3,12 @@ namespace Box\Spout\Reader\XLSX; use Box\Spout\Common\Exception\IOException; +use Box\Spout\Reader\Common\Entity\Options; use Box\Spout\Reader\Exception\XMLProcessingException; use Box\Spout\Reader\IteratorInterface; 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\CellValueFormatter; 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 $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 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->sheetDataXMLFilePath = $this->normalizeSheetDataXMLFilePath($sheetDataXMLFilePath); - $this->xmlReader = new XMLReader(); + $this->xmlReader = $entityFactory->createXMLReader(); - $this->styleHelper = new StyleHelper($filePath); - $this->cellValueFormatter = new CellValueFormatter($sharedStringsHelper, $this->styleHelper, $options->shouldFormatDates()); + $this->styleHelper = $helperFactory->createStyleHelper($filePath, $entityFactory); + $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 - $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_ROW, XMLProcessor::NODE_TYPE_START, [$this, 'processRowStartingNode']); $this->xmlProcessor->registerCallback(self::XML_NODE_CELL, XMLProcessor::NODE_TYPE_START, [$this, 'processCellStartingNode']); diff --git a/src/Spout/Reader/XLSX/Sheet.php b/src/Spout/Reader/XLSX/Sheet.php index 9baaef2..2894525 100644 --- a/src/Spout/Reader/XLSX/Sheet.php +++ b/src/Spout/Reader/XLSX/Sheet.php @@ -3,6 +3,7 @@ namespace Box\Spout\Reader\XLSX; use Box\Spout\Reader\SheetInterface; +use Box\Spout\Reader\XLSX\Creator\EntityFactory; /** * 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 string $sheetName Name of the sheet * @param bool $isSheetActive Whether the sheet was defined as active - * @param \Box\Spout\Reader\XLSX\ReaderOptions $options Reader's current options - * @param Helper\SharedStringsHelper Helper to work with shared strings + * @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager Reader's options manager + * @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->name = $sheetName; $this->isActive = $isSheetActive; diff --git a/src/Spout/Reader/XLSX/SheetIterator.php b/src/Spout/Reader/XLSX/SheetIterator.php index 7ba07d3..de9cce2 100644 --- a/src/Spout/Reader/XLSX/SheetIterator.php +++ b/src/Spout/Reader/XLSX/SheetIterator.php @@ -3,6 +3,8 @@ namespace Box\Spout\Reader\XLSX; 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\Exception\NoSheetsFoundException; @@ -22,15 +24,23 @@ class SheetIterator implements IteratorInterface /** * @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\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 */ - public function __construct($filePath, $options, $sharedStringsHelper, $globalFunctionsHelper) + public function __construct( + $filePath, + $optionsManager, + $sharedStringsHelper, + $globalFunctionsHelper, + $entityFactory, + $helperFactory) { // Fetch all available sheets - $sheetHelper = new SheetHelper($filePath, $options, $sharedStringsHelper, $globalFunctionsHelper); + $sheetHelper = $helperFactory->createSheetHelper($filePath, $optionsManager, $sharedStringsHelper, $globalFunctionsHelper, $entityFactory); $this->sheets = $sheetHelper->getSheets(); if (count($this->sheets) === 0) { diff --git a/src/Spout/Writer/CSV/Manager/OptionsManager.php b/src/Spout/Writer/CSV/Manager/OptionsManager.php index 502ce94..e9e0eb2 100644 --- a/src/Spout/Writer/CSV/Manager/OptionsManager.php +++ b/src/Spout/Writer/CSV/Manager/OptionsManager.php @@ -3,7 +3,7 @@ namespace Box\Spout\Writer\CSV\Manager; use Box\Spout\Writer\Common\Entity\Options; -use Box\Spout\Writer\Common\Manager\OptionsManagerAbstract; +use Box\Spout\Common\Manager\OptionsManagerAbstract; /** * Class OptionsManager @@ -34,4 +34,4 @@ class OptionsManager extends OptionsManagerAbstract $this->setOption(Options::FIELD_ENCLOSURE, '"'); $this->setOption(Options::SHOULD_ADD_BOM, true); } -} \ No newline at end of file +} diff --git a/src/Spout/Writer/Common/Creator/InternalFactoryInterface.php b/src/Spout/Writer/Common/Creator/InternalFactoryInterface.php index dd0dd72..5c39661 100644 --- a/src/Spout/Writer/Common/Creator/InternalFactoryInterface.php +++ b/src/Spout/Writer/Common/Creator/InternalFactoryInterface.php @@ -2,7 +2,7 @@ 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; /** @@ -17,4 +17,4 @@ interface InternalFactoryInterface * @return WorkbookManagerInterface */ public function createWorkbookManager(OptionsManagerInterface $optionsManager); -} \ No newline at end of file +} diff --git a/src/Spout/Writer/Common/Entity/Options.php b/src/Spout/Writer/Common/Entity/Options.php index 2641f72..36c1993 100644 --- a/src/Spout/Writer/Common/Entity/Options.php +++ b/src/Spout/Writer/Common/Entity/Options.php @@ -4,7 +4,7 @@ namespace Box\Spout\Writer\Common\Entity; /** * Class Options - * Writer' options holder + * Writers' options holder * * @package Box\Spout\Writer\Common\Entity */ diff --git a/src/Spout/Writer/Common/Manager/WorkbookManagerAbstract.php b/src/Spout/Writer/Common/Manager/WorkbookManagerAbstract.php index c10af47..514674b 100644 --- a/src/Spout/Writer/Common/Manager/WorkbookManagerAbstract.php +++ b/src/Spout/Writer/Common/Manager/WorkbookManagerAbstract.php @@ -3,6 +3,7 @@ namespace Box\Spout\Writer\Common\Manager; use Box\Spout\Common\Exception\IOException; +use Box\Spout\Common\Manager\OptionsManagerInterface; use Box\Spout\Writer\Common\Helper\FileSystemWithRootFolderHelperInterface; use Box\Spout\Writer\Common\Entity\Options; use Box\Spout\Writer\Common\Manager\Style\StyleManagerInterface; @@ -312,4 +313,4 @@ abstract class WorkbookManagerAbstract implements WorkbookManagerInterface $rootFolder = $this->fileSystemHelper->getRootFolder(); $this->fileSystemHelper->deleteFolderRecursively($rootFolder); } -} \ No newline at end of file +} diff --git a/src/Spout/Writer/ODS/Creator/InternalFactory.php b/src/Spout/Writer/ODS/Creator/InternalFactory.php index 885bff3..6720005 100644 --- a/src/Spout/Writer/ODS/Creator/InternalFactory.php +++ b/src/Spout/Writer/ODS/Creator/InternalFactory.php @@ -4,7 +4,7 @@ namespace Box\Spout\Writer\ODS\Creator; use Box\Spout\Common\Helper\StringHelper; 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\Creator\EntityFactory; use Box\Spout\Writer\Common\Creator\InternalFactoryInterface; @@ -119,4 +119,4 @@ class InternalFactory implements InternalFactoryInterface { return new StringHelper(); } -} \ No newline at end of file +} diff --git a/src/Spout/Writer/ODS/Manager/OptionsManager.php b/src/Spout/Writer/ODS/Manager/OptionsManager.php index 4a83428..ccc81b9 100644 --- a/src/Spout/Writer/ODS/Manager/OptionsManager.php +++ b/src/Spout/Writer/ODS/Manager/OptionsManager.php @@ -3,7 +3,7 @@ namespace Box\Spout\Writer\ODS\Manager; 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; /** @@ -48,4 +48,4 @@ class OptionsManager extends OptionsManagerAbstract $this->setOption(Options::DEFAULT_ROW_STYLE, $this->styleBuilder->build()); $this->setOption(Options::SHOULD_CREATE_NEW_SHEETS_AUTOMATICALLY, true); } -} \ No newline at end of file +} diff --git a/src/Spout/Writer/WriterAbstract.php b/src/Spout/Writer/WriterAbstract.php index 7569ff2..2c20142 100644 --- a/src/Spout/Writer/WriterAbstract.php +++ b/src/Spout/Writer/WriterAbstract.php @@ -9,7 +9,7 @@ use Box\Spout\Common\Helper\FileSystemHelper; use Box\Spout\Common\Helper\GlobalFunctionsHelper; use Box\Spout\Writer\Common\Entity\Options; 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\Exception\WriterAlreadyOpenedException; use Box\Spout\Writer\Exception\WriterNotOpenedException; diff --git a/src/Spout/Writer/WriterMultiSheetsAbstract.php b/src/Spout/Writer/WriterMultiSheetsAbstract.php index f76a150..9d5a0c6 100644 --- a/src/Spout/Writer/WriterMultiSheetsAbstract.php +++ b/src/Spout/Writer/WriterMultiSheetsAbstract.php @@ -4,7 +4,7 @@ namespace Box\Spout\Writer; use Box\Spout\Common\Helper\GlobalFunctionsHelper; 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\Worksheet; use Box\Spout\Writer\Common\Manager\Style\StyleMerger; diff --git a/src/Spout/Writer/XLSX/Creator/InternalFactory.php b/src/Spout/Writer/XLSX/Creator/InternalFactory.php index 9fd312a..8a2f29a 100644 --- a/src/Spout/Writer/XLSX/Creator/InternalFactory.php +++ b/src/Spout/Writer/XLSX/Creator/InternalFactory.php @@ -8,7 +8,7 @@ use Box\Spout\Writer\Common\Creator\EntityFactory; use Box\Spout\Writer\Common\Creator\InternalFactoryInterface; use Box\Spout\Writer\Common\Entity\Options; 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\Manager\SharedStringsManager; use Box\Spout\Writer\XLSX\Manager\Style\StyleManager; @@ -140,4 +140,4 @@ class InternalFactory implements InternalFactoryInterface { return new StringHelper(); } -} \ No newline at end of file +} diff --git a/src/Spout/Writer/XLSX/Manager/OptionsManager.php b/src/Spout/Writer/XLSX/Manager/OptionsManager.php index 425f2f6..3aac2a7 100644 --- a/src/Spout/Writer/XLSX/Manager/OptionsManager.php +++ b/src/Spout/Writer/XLSX/Manager/OptionsManager.php @@ -3,7 +3,7 @@ namespace Box\Spout\Writer\XLSX\Manager; 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; /** @@ -59,4 +59,4 @@ class OptionsManager extends OptionsManagerAbstract $this->setOption(Options::SHOULD_CREATE_NEW_SHEETS_AUTOMATICALLY, true); $this->setOption(Options::SHOULD_USE_INLINE_STRINGS, true); } -} \ No newline at end of file +} diff --git a/src/Spout/Writer/XLSX/Manager/WorksheetManager.php b/src/Spout/Writer/XLSX/Manager/WorksheetManager.php index 6a03dad..4057cf0 100644 --- a/src/Spout/Writer/XLSX/Manager/WorksheetManager.php +++ b/src/Spout/Writer/XLSX/Manager/WorksheetManager.php @@ -6,7 +6,7 @@ use Box\Spout\Common\Exception\InvalidArgumentException; use Box\Spout\Common\Exception\IOException; use Box\Spout\Common\Helper\StringHelper; 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\Cell; use Box\Spout\Writer\Common\Entity\Worksheet; @@ -265,4 +265,4 @@ EOD; fwrite($worksheetFilePointer, ''); fclose($worksheetFilePointer); } -} \ No newline at end of file +} diff --git a/tests/Spout/Writer/Common/Manager/OptionsManagerTest.php b/tests/Spout/Common/Manager/OptionsManagerTest.php similarity index 95% rename from tests/Spout/Writer/Common/Manager/OptionsManagerTest.php rename to tests/Spout/Common/Manager/OptionsManagerTest.php index 7598bcc..7a205f6 100644 --- a/tests/Spout/Writer/Common/Manager/OptionsManagerTest.php +++ b/tests/Spout/Common/Manager/OptionsManagerTest.php @@ -1,11 +1,11 @@ setOption('foo', 'foo-val'); $this->setOption('bar', false); } -} \ No newline at end of file +} diff --git a/tests/Spout/Reader/CSV/ReaderTest.php b/tests/Spout/Reader/CSV/ReaderTest.php index 429ffa6..4c705cf 100644 --- a/tests/Spout/Reader/CSV/ReaderTest.php +++ b/tests/Spout/Reader/CSV/ReaderTest.php @@ -2,9 +2,14 @@ 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\Common\Type; use Box\Spout\Common\Helper\EncodingHelper; +use Box\Spout\Reader\ReaderInterface; use Box\Spout\TestUsingResource; /** @@ -23,7 +28,7 @@ class ReaderTest extends \PHPUnit_Framework_TestCase */ 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() { - ReaderFactory::create(Type::CSV)->getSheetIterator(); + $this->createCSVReader()->getSheetIterator(); } /** @@ -43,6 +48,7 @@ class ReaderTest extends \PHPUnit_Framework_TestCase */ public function testOpenShouldThrowExceptionIfFileNotReadable() { + /** @var \Box\Spout\Common\Helper\GlobalFunctionsHelper|\PHPUnit_Framework_MockObject_MockObject $helperStub */ $helperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\GlobalFunctionsHelper') ->setMethods(['is_readable']) ->getMock(); @@ -50,8 +56,7 @@ class ReaderTest extends \PHPUnit_Framework_TestCase $resourcePath = $this->getResourcePath('csv_standard.csv'); - $reader = ReaderFactory::create(Type::CSV); - $reader->setGlobalFunctionsHelper($helperStub); + $reader = $this->createCSVReader(null, $helperStub); $reader->open($resourcePath); } @@ -62,6 +67,7 @@ class ReaderTest extends \PHPUnit_Framework_TestCase */ public function testOpenShouldThrowExceptionIfCannotOpenFile() { + /** @var \Box\Spout\Common\Helper\GlobalFunctionsHelper|\PHPUnit_Framework_MockObject_MockObject $helperStub */ $helperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\GlobalFunctionsHelper') ->setMethods(['fopen']) ->getMock(); @@ -69,8 +75,7 @@ class ReaderTest extends \PHPUnit_Framework_TestCase $resourcePath = $this->getResourcePath('csv_standard.csv'); - $reader = ReaderFactory::create(Type::CSV); - $reader->setGlobalFunctionsHelper($helperStub); + $reader = $this->createCSVReader(null, $helperStub); $reader->open($resourcePath); } @@ -139,7 +144,7 @@ class ReaderTest extends \PHPUnit_Framework_TestCase { $allRows = $this->getAllRowsForFile( 'csv_with_multiple_empty_lines.csv', - ',', '"', "\n", EncodingHelper::ENCODING_UTF8, + ',', '"', EncodingHelper::ENCODING_UTF8, $shouldPreserveEmptyRows = true ); @@ -215,21 +220,6 @@ class ReaderTest extends \PHPUnit_Framework_TestCase $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 */ @@ -262,7 +252,7 @@ class ReaderTest extends \PHPUnit_Framework_TestCase */ public function testReadShouldSkipBom($fileName, $fileEncoding) { - $allRows = $this->getAllRowsForFile($fileName, ',', '"', "\n", $fileEncoding); + $allRows = $this->getAllRowsForFile($fileName, ',', '"', $fileEncoding); $expectedRows = [ ['csv--11', 'csv--12', 'csv--13'], @@ -313,9 +303,8 @@ class ReaderTest extends \PHPUnit_Framework_TestCase $helperStub->method('function_exists')->will($this->returnValueMap($returnValueMap)); /** @var \Box\Spout\Reader\CSV\Reader $reader */ - $reader = ReaderFactory::create(Type::CSV); + $reader = $this->createCSVReader(null, $helperStub); $reader - ->setGlobalFunctionsHelper($helperStub) ->setEncoding($fileEncoding) ->open($resourcePath); @@ -343,7 +332,7 @@ class ReaderTest extends \PHPUnit_Framework_TestCase $allRows = []; $resourcePath = $this->getResourcePath('csv_standard.csv'); - $reader = ReaderFactory::create(Type::CSV); + $reader = $this->createCSVReader(); $reader->open($resourcePath); 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'); } - /** - * @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 */ @@ -481,7 +429,7 @@ class ReaderTest extends \PHPUnit_Framework_TestCase stream_wrapper_register('spout', SpoutTestStream::CLASS_NAME); /** @var \Box\Spout\Reader\CSV\Reader $reader */ - $reader = ReaderFactory::create(Type::CSV); + $reader = $this->createCSVReader(); $reader->open($resourcePath); foreach ($reader->getSheetIterator() as $sheet) { @@ -511,8 +459,60 @@ class ReaderTest extends \PHPUnit_Framework_TestCase public function testReadWithUnsupportedCustomStreamWrapper() { /** @var \Box\Spout\Reader\CSV\Reader $reader */ - $reader = ReaderFactory::create(Type::CSV); + $reader = $this->createCSVReader(); $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; + } + } diff --git a/tests/Spout/Reader/XLSX/Helper/SharedStringsCaching/CachingStrategyFactoryTest.php b/tests/Spout/Reader/XLSX/Helper/SharedStringsCaching/CachingStrategyFactoryTest.php index e61760a..85ec84b 100644 --- a/tests/Spout/Reader/XLSX/Helper/SharedStringsCaching/CachingStrategyFactoryTest.php +++ b/tests/Spout/Reader/XLSX/Helper/SharedStringsCaching/CachingStrategyFactoryTest.php @@ -1,6 +1,7 @@ method('getMemoryLimitInKB')->willReturn($memoryLimitInKB); - \ReflectionHelper::setStaticValue('\Box\Spout\Reader\XLSX\Helper\SharedStringsCaching\CachingStrategyFactory', 'instance', $factoryStub); - - $strategy = $factoryStub->getBestCachingStrategy($sharedStringsUniqueCount, null); + $tempFolder = sys_get_temp_dir(); + $helperFactory = new HelperFactory($factoryStub); + $strategy = $factoryStub->createBestCachingStrategy($sharedStringsUniqueCount, $tempFolder, $helperFactory); $fullExpectedStrategyClassName = 'Box\Spout\Reader\XLSX\Helper\SharedStringsCaching\\' . $expectedStrategyClassName; $this->assertEquals($fullExpectedStrategyClassName, get_class($strategy)); $strategy->clearCache(); - \ReflectionHelper::reset(); } /** diff --git a/tests/Spout/Reader/XLSX/Helper/SharedStringsHelperTest.php b/tests/Spout/Reader/XLSX/Helper/SharedStringsHelperTest.php index 17d1b52..41d48dc 100644 --- a/tests/Spout/Reader/XLSX/Helper/SharedStringsHelperTest.php +++ b/tests/Spout/Reader/XLSX/Helper/SharedStringsHelperTest.php @@ -2,6 +2,8 @@ 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\FileBasedStrategy; use Box\Spout\Reader\XLSX\Helper\SharedStringsCaching\InMemoryStrategy; @@ -24,8 +26,7 @@ class SharedStringsHelperTest extends \PHPUnit_Framework_TestCase */ public function setUp() { - $resourcePath = $this->getResourcePath('one_sheet_with_shared_strings.xlsx'); - $this->sharedStringsHelper = new SharedStringsHelper($resourcePath); + $this->sharedStringsHelper = null; } /** @@ -33,7 +34,26 @@ class SharedStringsHelperTest extends \PHPUnit_Framework_TestCase */ public function tearDown() { - $this->sharedStringsHelper->cleanup(); + if ($this->sharedStringsHelper !== null) { + $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; } /** @@ -42,8 +62,9 @@ class SharedStringsHelperTest extends \PHPUnit_Framework_TestCase */ public function testGetStringAtIndexShouldThrowExceptionIfStringNotFound() { - $this->sharedStringsHelper->extractSharedStrings(); - $this->sharedStringsHelper->getStringAtIndex(PHP_INT_MAX); + $sharedStringsHelper = $this->createSharedStringsHelper(); + $sharedStringsHelper->extractSharedStrings(); + $sharedStringsHelper->getStringAtIndex(PHP_INT_MAX); } /** @@ -51,15 +72,16 @@ class SharedStringsHelperTest extends \PHPUnit_Framework_TestCase */ 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); - $sharedString = $this->sharedStringsHelper->getStringAtIndex(24); + $sharedString = $sharedStringsHelper->getStringAtIndex(24); $this->assertEquals('s1--E5', $sharedString); - $usedCachingStrategy = \ReflectionHelper::getValueOnObject($this->sharedStringsHelper, 'cachingStrategy'); + $usedCachingStrategy = \ReflectionHelper::getValueOnObject($sharedStringsHelper, 'cachingStrategy'); $this->assertTrue($usedCachingStrategy instanceof InMemoryStrategy); } @@ -68,8 +90,7 @@ class SharedStringsHelperTest extends \PHPUnit_Framework_TestCase */ public function testGetStringAtIndexShouldWorkWithMultilineStrings() { - $resourcePath = $this->getResourcePath('one_sheet_with_shared_multiline_strings.xlsx'); - $sharedStringsHelper = new SharedStringsHelper($resourcePath); + $sharedStringsHelper = $this->createSharedStringsHelper('one_sheet_with_shared_multiline_strings.xlsx'); $sharedStringsHelper->extractSharedStrings(); @@ -78,8 +99,6 @@ class SharedStringsHelperTest extends \PHPUnit_Framework_TestCase $sharedString = $sharedStringsHelper->getStringAtIndex(24); $this->assertEquals("s1\nE5", $sharedString); - - $sharedStringsHelper->cleanup(); } /** @@ -87,15 +106,12 @@ class SharedStringsHelperTest extends \PHPUnit_Framework_TestCase */ public function testGetStringAtIndexShouldWorkWithStringsContainingTextAndHyperlinkInSameCell() { - $resourcePath = $this->getResourcePath('one_sheet_with_shared_strings_containing_text_and_hyperlink_in_same_cell.xlsx'); - $sharedStringsHelper = new SharedStringsHelper($resourcePath); + $sharedStringsHelper = $this->createSharedStringsHelper('one_sheet_with_shared_strings_containing_text_and_hyperlink_in_same_cell.xlsx'); $sharedStringsHelper->extractSharedStrings(); $sharedString = $sharedStringsHelper->getStringAtIndex(0); $this->assertEquals('go to https://github.com please', $sharedString); - - $sharedStringsHelper->cleanup(); } /** @@ -103,15 +119,12 @@ class SharedStringsHelperTest extends \PHPUnit_Framework_TestCase */ public function testGetStringAtIndexShouldNotDoubleDecodeHTMLEntities() { - $resourcePath = $this->getResourcePath('one_sheet_with_pre_encoded_html_entities.xlsx'); - $sharedStringsHelper = new SharedStringsHelper($resourcePath); + $sharedStringsHelper = $this->createSharedStringsHelper('one_sheet_with_pre_encoded_html_entities.xlsx'); $sharedStringsHelper->extractSharedStrings(); $sharedString = $sharedStringsHelper->getStringAtIndex(0); $this->assertEquals('quote: " - ampersand: &', $sharedString); - - $sharedStringsHelper->cleanup(); } /** @@ -123,8 +136,7 @@ class SharedStringsHelperTest extends \PHPUnit_Framework_TestCase $originalMemoryLimit = ini_get('memory_limit'); ini_set('memory_limit', '-1'); - $resourcePath = $this->getResourcePath('sheet_with_lots_of_shared_strings.xlsx'); - $sharedStringsHelper = new SharedStringsHelper($resourcePath); + $sharedStringsHelper = $this->createSharedStringsHelper('sheet_with_lots_of_shared_strings.xlsx'); $sharedStringsHelper->extractSharedStrings(); @@ -137,8 +149,6 @@ class SharedStringsHelperTest extends \PHPUnit_Framework_TestCase $usedCachingStrategy = \ReflectionHelper::getValueOnObject($sharedStringsHelper, 'cachingStrategy'); $this->assertTrue($usedCachingStrategy instanceof FileBasedStrategy); - $sharedStringsHelper->cleanup(); - ini_set('memory_limit', $originalMemoryLimit); } } diff --git a/tests/Spout/Reader/XLSX/Helper/StyleHelperTest.php b/tests/Spout/Reader/XLSX/Helper/StyleHelperTest.php index 8d45fa5..efbaedd 100644 --- a/tests/Spout/Reader/XLSX/Helper/StyleHelperTest.php +++ b/tests/Spout/Reader/XLSX/Helper/StyleHelperTest.php @@ -1,6 +1,9 @@ getMockBuilder('\Box\Spout\Reader\XLSX\Helper\StyleHelper') - ->setConstructorArgs(['/path/to/file.xlsx']) + ->setConstructorArgs(['/path/to/file.xlsx', $entityFactory]) ->setMethods(['getCustomNumberFormats', 'getStylesAttributes']) ->getMock();