merge, resolve conflicts

This commit is contained in:
madflow 2017-09-29 11:22:39 +02:00
commit 6971a793ef
182 changed files with 2238 additions and 1781 deletions

4
.gitattributes vendored
View File

@ -1,11 +1,11 @@
# Ignore all test and documentation for archive # Ignore all test, documentation and dot files for archive
/tests export-ignore /tests export-ignore
/.editorconfig export-ignore /.editorconfig export-ignore
/.gitattributes export-ignore /.gitattributes export-ignore
/.gitignore export-ignore /.gitignore export-ignore
/.php_cs.dist export-ignore
/.scrutinizer.yml export-ignore /.scrutinizer.yml export-ignore
/.travis.yml export-ignore /.travis.yml export-ignore
/composer.lock export-ignore
/CONTRIBUTING.md export-ignore /CONTRIBUTING.md export-ignore
/logo.png export-ignore /logo.png export-ignore
/phpunit.xml export-ignore /phpunit.xml export-ignore

8
.gitignore vendored
View File

@ -1,6 +1,8 @@
/.idea
*.iml
/tests/resources/generated /tests/resources/generated
/tests/coverage /tests/coverage
/vendor /vendor
/.idea /composer.lock
*.iml /.php_cs.cache
composer.lock

58
.php_cs.dist Normal file
View File

@ -0,0 +1,58 @@
<?php
$config = PhpCsFixer\Config::create()
->setRiskyAllowed(true)
->setRules([
'@Symfony' => true,
'align_multiline_comment' => false,
'array_syntax' => ['syntax' => 'short'],
'binary_operator_spaces' => ['align_double_arrow' => true, 'align_equals' => null],
'blank_line_before_statement' => ['statements' => ['return']],
'combine_consecutive_unsets' => true,
'concat_space' => ['spacing' => 'one'],
'declare_equal_normalize' => ['space' => 'single'],
'heredoc_to_nowdoc' => true,
'is_null' => ['use_yoda_style' => false],
'method_argument_space' => ['ensure_fully_multiline' => true],
'modernize_types_casting' => true,
'no_break_comment' => ['comment_text' => 'do nothing'],
'no_empty_phpdoc' => false,
'no_null_property_initialization' => true,
'no_short_echo_tag' => true,
'no_superfluous_elseif' => true,
'no_unneeded_control_parentheses' => ['statements' => ['break', 'clone', 'continue', 'echo_print', 'switch_case', 'yield']],
'no_unneeded_curly_braces' => true,
'no_unneeded_final_method' => true,
'no_useless_else' => false,
'no_useless_return' => true,
'ordered_imports' => true,
'phpdoc_add_missing_param_annotation' => true,
'phpdoc_align' => false,
'phpdoc_annotation_without_dot' => false,
'phpdoc_no_empty_return' => false,
'phpdoc_order' => true,
'phpdoc_summary' => false,
'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'],
'phpdoc_separation' => false,
'pre_increment' => false,
'protected_to_private' => true,
'psr4' => true,
'return_type_declaration' => ['space_before' => 'one'],
'semicolon_after_instruction' => true,
'simplified_null_return' => false,
'single_line_comment_style' => ['comment_types' => ['hash']],
'strict_comparison' => true,
'void_return' => true,
]);
$config->setFinder(
PhpCsFixer\Finder::create()
->exclude('vendor')
->in(__DIR__)
->name('*.php')
);
$cacheDir = getenv('TRAVIS') ? getenv('HOME') . '/.php-cs-fixer' : __DIR__;
$config->setCacheFile($cacheDir . '/.php_cs.cache');
return $config;

View File

@ -1,27 +1,60 @@
dist: trusty
sudo: false
language: php language: php
dist: trusty matrix:
include:
php: - php: 5.6
- 5.6 env: WITH_PHPUNIT=true
- 7.0 - php: 5.6
- 7.1 env: WITH_CS=true
- hhvm-3.6 - php: 7.0
env: WITH_PHPUNIT=true
- php: 7.1
env: WITH_PHPUNIT=true WITH_COVERAGE=true
- php: hhvm-3.6
env: WITH_PHPUNIT=true
cache: cache:
directories: directories:
- $HOME/.composer/cache - $HOME/.composer/cache
- $HOME/.php-cs-fixer
before_install:
- |
if [[ "$WITH_COVERAGE" != "true" ]]; then
phpenv config-rm xdebug.ini
fi
if [[ "$WITH_CS" != "true" ]]; then
composer remove friendsofphp/php-cs-fixer --dev --no-update
fi
- composer validate
install: install:
- composer install --no-interaction --prefer-source - composer install --no-interaction --prefer-source
script: before_script:
- mkdir -p "$HOME/.php-cs-fixer"
- mkdir -p build/logs - mkdir -p build/logs
- php vendor/bin/phpunit --coverage-clover=build/logs/coverage.clover
script:
- |
if [[ "$WITH_CS" == "true" ]]; then
vendor/bin/php-cs-fixer fix --config=.php_cs.dist --verbose --diff --dry-run
fi
- |
if [[ "$WITH_PHPUNIT" == "true" ]]; then
if [[ "$WITH_COVERAGE" == "true" ]]; then
vendor/bin/phpunit --coverage-clover=build/logs/coverage.clover
else
vendor/bin/phpunit --no-coverage
fi
fi
after_script: after_script:
- | - |
if [[ "$TRAVIS_PHP_VERSION" = '7.1' ]]; then if [[ "$WITH_COVERAGE" == "true" ]]; then
wget https://scrutinizer-ci.com/ocular.phar wget https://scrutinizer-ci.com/ocular.phar
php ocular.phar code-coverage:upload --format=php-clover build/logs/coverage.clover php ocular.phar code-coverage:upload --format=php-clover build/logs/coverage.clover
fi fi

View File

@ -17,7 +17,8 @@
"ext-xmlreader" : "*" "ext-xmlreader" : "*"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^5.7.0" "phpunit/phpunit": "^5.7.0",
"friendsofphp/php-cs-fixer": "^2.5.0"
}, },
"suggest": { "suggest": {
"ext-iconv": "To handle non UTF-8 CSV files (if \"php-intl\" is not already installed or is too limited)", "ext-iconv": "To handle non UTF-8 CSV files (if \"php-intl\" is not already installed or is too limited)",

View File

@ -5,8 +5,6 @@ namespace Box\Spout\Autoloader;
/** /**
* Class Psr4Autoloader * Class Psr4Autoloader
* @see https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader-examples.md#class-example * @see https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader-examples.md#class-example
*
* @package Box\Spout\Autoloader
*/ */
class Psr4Autoloader class Psr4Autoloader
{ {
@ -16,7 +14,7 @@ class Psr4Autoloader
* *
* @var array * @var array
*/ */
protected $prefixes = array(); protected $prefixes = [];
/** /**
* Register loader with SPL autoloader stack. * Register loader with SPL autoloader stack.
@ -25,7 +23,7 @@ class Psr4Autoloader
*/ */
public function register() public function register()
{ {
spl_autoload_register(array($this, 'loadClass')); spl_autoload_register([$this, 'loadClass']);
} }
/** /**
@ -49,7 +47,7 @@ class Psr4Autoloader
// initialize the namespace prefix array // initialize the namespace prefix array
if (isset($this->prefixes[$prefix]) === false) { if (isset($this->prefixes[$prefix]) === false) {
$this->prefixes[$prefix] = array(); $this->prefixes[$prefix] = [];
} }
// retain the base directory for the namespace prefix // retain the base directory for the namespace prefix
@ -75,7 +73,6 @@ class Psr4Autoloader
// work backwards through the namespace names of the fully-qualified // work backwards through the namespace names of the fully-qualified
// class name to find a mapped file name // class name to find a mapped file name
while (false !== $pos = strrpos($prefix, '\\')) { while (false !== $pos = strrpos($prefix, '\\')) {
// retain the trailing namespace separator in the prefix // retain the trailing namespace separator in the prefix
$prefix = substr($class, 0, $pos + 1); $prefix = substr($class, 0, $pos + 1);
@ -114,7 +111,6 @@ class Psr4Autoloader
// look through base directories for this namespace prefix // look through base directories for this namespace prefix
foreach ($this->prefixes[$prefix] as $baseDir) { foreach ($this->prefixes[$prefix] as $baseDir) {
// replace the namespace prefix with the base directory, // replace the namespace prefix with the base directory,
// replace namespace separators with directory separators // replace namespace separators with directory separators
// in the relative class name, append with .php // in the relative class name, append with .php
@ -143,8 +139,10 @@ class Psr4Autoloader
{ {
if (file_exists($file)) { if (file_exists($file)) {
require $file; require $file;
return true; return true;
} }
return false; return false;
} }
} }

View File

@ -5,7 +5,7 @@ namespace Box\Spout\Autoloader;
require_once 'Psr4Autoloader.php'; require_once 'Psr4Autoloader.php';
/** /**
* @var string $srcBaseDirectory * @var string
* Full path to "src/Spout" which is what we want "Box\Spout" to map to. * Full path to "src/Spout" which is what we want "Box\Spout" to map to.
*/ */
$srcBaseDirectory = dirname(dirname(__FILE__)); $srcBaseDirectory = dirname(dirname(__FILE__));

View File

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

View File

@ -6,7 +6,6 @@ namespace Box\Spout\Common\Exception;
* Class EncodingConversionException * Class EncodingConversionException
* *
* @api * @api
* @package Box\Spout\Common\Exception
*/ */
class EncodingConversionException extends SpoutException class EncodingConversionException extends SpoutException
{ {

View File

@ -6,7 +6,6 @@ namespace Box\Spout\Common\Exception;
* Class IOException * Class IOException
* *
* @api * @api
* @package Box\Spout\Common\Exception
*/ */
class IOException extends SpoutException class IOException extends SpoutException
{ {

View File

@ -6,7 +6,6 @@ namespace Box\Spout\Common\Exception;
* Class InvalidArgumentException * Class InvalidArgumentException
* *
* @api * @api
* @package Box\Spout\Common\Exception
*/ */
class InvalidArgumentException extends SpoutException class InvalidArgumentException extends SpoutException
{ {

View File

@ -5,7 +5,6 @@ namespace Box\Spout\Common\Exception;
/** /**
* Class SpoutException * Class SpoutException
* *
* @package Box\Spout\Common\Exception
* @abstract * @abstract
*/ */
abstract class SpoutException extends \Exception abstract class SpoutException extends \Exception

View File

@ -6,7 +6,6 @@ namespace Box\Spout\Common\Exception;
* Class UnsupportedTypeException * Class UnsupportedTypeException
* *
* @api * @api
* @package Box\Spout\Common\Exception
*/ */
class UnsupportedTypeException extends SpoutException class UnsupportedTypeException extends SpoutException
{ {

View File

@ -7,8 +7,6 @@ use Box\Spout\Common\Exception\EncodingConversionException;
/** /**
* Class EncodingHelper * Class EncodingHelper
* This class provides helper functions to work with encodings. * This class provides helper functions to work with encodings.
*
* @package Box\Spout\Common\Helper
*/ */
class EncodingHelper class EncodingHelper
{ {
@ -97,8 +95,8 @@ class EncodingHelper
* *
* @param string $string Non UTF-8 string to be converted * @param string $string Non UTF-8 string to be converted
* @param string $sourceEncoding The encoding used to encode the source string * @param string $sourceEncoding The encoding used to encode the source string
* @return string The converted, UTF-8 string
* @throws \Box\Spout\Common\Exception\EncodingConversionException If conversion is not supported or if the conversion failed * @throws \Box\Spout\Common\Exception\EncodingConversionException If conversion is not supported or if the conversion failed
* @return string The converted, UTF-8 string
*/ */
public function attemptConversionToUTF8($string, $sourceEncoding) public function attemptConversionToUTF8($string, $sourceEncoding)
{ {
@ -110,8 +108,8 @@ class EncodingHelper
* *
* @param string $string UTF-8 string to be converted * @param string $string UTF-8 string to be converted
* @param string $targetEncoding The encoding the string should be re-encoded into * @param string $targetEncoding The encoding the string should be re-encoded into
* @return string The converted string, encoded with the given encoding
* @throws \Box\Spout\Common\Exception\EncodingConversionException If conversion is not supported or if the conversion failed * @throws \Box\Spout\Common\Exception\EncodingConversionException If conversion is not supported or if the conversion failed
* @return string The converted string, encoded with the given encoding
*/ */
public function attemptConversionFromUTF8($string, $targetEncoding) public function attemptConversionFromUTF8($string, $targetEncoding)
{ {
@ -125,8 +123,8 @@ class EncodingHelper
* @param string $string string to be converted * @param string $string string to be converted
* @param string $sourceEncoding The encoding used to encode the source string * @param string $sourceEncoding The encoding used to encode the source string
* @param string $targetEncoding The encoding the string should be re-encoded into * @param string $targetEncoding The encoding the string should be re-encoded into
* @return string The converted string, encoded with the given encoding
* @throws \Box\Spout\Common\Exception\EncodingConversionException If conversion is not supported or if the conversion failed * @throws \Box\Spout\Common\Exception\EncodingConversionException If conversion is not supported or if the conversion failed
* @return string The converted string, encoded with the given encoding
*/ */
protected function attemptConversion($string, $sourceEncoding, $targetEncoding) protected function attemptConversion($string, $sourceEncoding, $targetEncoding)
{ {

View File

@ -1,12 +1,10 @@
<?php <?php
namespace Box\Spout\Common\Escaper; namespace Box\Spout\Common\Helper\Escaper;
/** /**
* Class CSV * Class CSV
* Provides functions to escape and unescape data for CSV files * Provides functions to escape and unescape data for CSV files
*
* @package Box\Spout\Common\Escaper
*/ */
class CSV implements EscaperInterface class CSV implements EscaperInterface
{ {

View File

@ -1,11 +1,9 @@
<?php <?php
namespace Box\Spout\Common\Escaper; namespace Box\Spout\Common\Helper\Escaper;
/** /**
* Interface EscaperInterface * Interface EscaperInterface
*
* @package Box\Spout\Common\Escaper
*/ */
interface EscaperInterface interface EscaperInterface
{ {

View File

@ -1,19 +1,13 @@
<?php <?php
namespace Box\Spout\Common\Escaper; namespace Box\Spout\Common\Helper\Escaper;
use Box\Spout\Common\Singleton;
/** /**
* Class ODS * Class ODS
* Provides functions to escape and unescape data for ODS files * Provides functions to escape and unescape data for ODS files
*
* @package Box\Spout\Common\Escaper
*/ */
class ODS implements EscaperInterface class ODS implements EscaperInterface
{ {
use Singleton;
/** /**
* Escapes the given string to make it compatible with XLSX * Escapes the given string to make it compatible with XLSX
* *

View File

@ -1,36 +1,37 @@
<?php <?php
namespace Box\Spout\Common\Escaper; namespace Box\Spout\Common\Helper\Escaper;
use Box\Spout\Common\Singleton;
/** /**
* Class XLSX * Class XLSX
* Provides functions to escape and unescape data for XLSX files * Provides functions to escape and unescape data for XLSX files
*
* @package Box\Spout\Common\Escaper
*/ */
class XLSX implements EscaperInterface class XLSX implements EscaperInterface
{ {
use Singleton; /** @var bool Whether the escaper has already been initialized */
private $isAlreadyInitialized = false;
/** @var string Regex pattern to detect control characters that need to be escaped */ /** @var string Regex pattern to detect control characters that need to be escaped */
protected $escapableControlCharactersPattern; private $escapableControlCharactersPattern;
/** @var string[] Map containing control characters to be escaped (key) and their escaped value (value) */ /** @var string[] Map containing control characters to be escaped (key) and their escaped value (value) */
protected $controlCharactersEscapingMap; private $controlCharactersEscapingMap;
/** @var string[] Map containing control characters to be escaped (value) and their escaped value (key) */ /** @var string[] Map containing control characters to be escaped (value) and their escaped value (key) */
protected $controlCharactersEscapingReverseMap; private $controlCharactersEscapingReverseMap;
/** /**
* Initializes the singleton instance * Initializes the control characters if not already done
*/ */
protected function init() protected function initIfNeeded()
{ {
if (!$this->isAlreadyInitialized) {
$this->escapableControlCharactersPattern = $this->getEscapableControlCharactersPattern(); $this->escapableControlCharactersPattern = $this->getEscapableControlCharactersPattern();
$this->controlCharactersEscapingMap = $this->getControlCharactersEscapingMap(); $this->controlCharactersEscapingMap = $this->getControlCharactersEscapingMap();
$this->controlCharactersEscapingReverseMap = array_flip($this->controlCharactersEscapingMap); $this->controlCharactersEscapingReverseMap = array_flip($this->controlCharactersEscapingMap);
$this->isAlreadyInitialized = true;
}
} }
/** /**
@ -41,6 +42,8 @@ class XLSX implements EscaperInterface
*/ */
public function escape($string) public function escape($string)
{ {
$this->initIfNeeded();
$escapedString = $this->escapeControlCharacters($string); $escapedString = $this->escapeControlCharacters($string);
// @NOTE: Using ENT_NOQUOTES as only XML entities ('<', '>', '&') need to be encoded. // @NOTE: Using ENT_NOQUOTES as only XML entities ('<', '>', '&') need to be encoded.
// Single and double quotes can be left as is. // Single and double quotes can be left as is.
@ -57,6 +60,8 @@ class XLSX implements EscaperInterface
*/ */
public function unescape($string) public function unescape($string)
{ {
$this->initIfNeeded();
// ============== // ==============
// = WARNING = // = WARNING =
// ============== // ==============
@ -88,7 +93,7 @@ class XLSX implements EscaperInterface
* "\t", "\r" and "\n" don't need to be escaped. * "\t", "\r" and "\n" don't need to be escaped.
* *
* NOTE: the logic has been adapted from the XlsxWriter library (BSD License) * NOTE: the logic has been adapted from the XlsxWriter library (BSD License)
* @link https://github.com/jmcnamara/XlsxWriter/blob/f1e610f29/xlsxwriter/sharedstrings.py#L89 * @see https://github.com/jmcnamara/XlsxWriter/blob/f1e610f29/xlsxwriter/sharedstrings.py#L89
* *
* @return string[] * @return string[]
*/ */
@ -117,7 +122,7 @@ class XLSX implements EscaperInterface
* So "\0" -> _x0000_ and "_x0000_" -> _x005F_x0000_. * So "\0" -> _x0000_ and "_x0000_" -> _x005F_x0000_.
* *
* NOTE: the logic has been adapted from the XlsxWriter library (BSD License) * NOTE: the logic has been adapted from the XlsxWriter library (BSD License)
* @link https://github.com/jmcnamara/XlsxWriter/blob/f1e610f29/xlsxwriter/sharedstrings.py#L89 * @see https://github.com/jmcnamara/XlsxWriter/blob/f1e610f29/xlsxwriter/sharedstrings.py#L89
* *
* @param string $string String to escape * @param string $string String to escape
* @return string * @return string
@ -155,7 +160,7 @@ class XLSX implements EscaperInterface
* So "_x0000_" -> "\0" and "_x005F_x0000_" -> "_x0000_" * So "_x0000_" -> "\0" and "_x005F_x0000_" -> "_x0000_"
* *
* NOTE: the logic has been adapted from the XlsxWriter library (BSD License) * NOTE: the logic has been adapted from the XlsxWriter library (BSD License)
* @link https://github.com/jmcnamara/XlsxWriter/blob/f1e610f29/xlsxwriter/sharedstrings.py#L89 * @see https://github.com/jmcnamara/XlsxWriter/blob/f1e610f29/xlsxwriter/sharedstrings.py#L89
* *
* @param string $string String to unescape * @param string $string String to unescape
* @return string * @return string

View File

@ -8,8 +8,6 @@ use Box\Spout\Common\Exception\IOException;
* Class FileSystemHelper * Class FileSystemHelper
* This class provides helper functions to help with the file system operations * This class provides helper functions to help with the file system operations
* like files/folders creation & deletion * like files/folders creation & deletion
*
* @package Box\Spout\Common\Helper
*/ */
class FileSystemHelper implements FileSystemHelperInterface class FileSystemHelper implements FileSystemHelperInterface
{ {
@ -29,8 +27,8 @@ class FileSystemHelper implements FileSystemHelperInterface
* *
* @param string $parentFolderPath The parent folder path under which the folder is going to be created * @param string $parentFolderPath The parent folder path under which the folder is going to be created
* @param string $folderName The name of the folder to create * @param string $folderName The name of the folder to create
* @return string Path of the created folder
* @throws \Box\Spout\Common\Exception\IOException If unable to create the folder or if the folder path is not inside of the base folder * @throws \Box\Spout\Common\Exception\IOException If unable to create the folder or if the folder path is not inside of the base folder
* @return string Path of the created folder
*/ */
public function createFolder($parentFolderPath, $folderName) public function createFolder($parentFolderPath, $folderName)
{ {
@ -53,8 +51,8 @@ class FileSystemHelper implements FileSystemHelperInterface
* @param string $parentFolderPath The parent folder path where the file is going to be created * @param string $parentFolderPath The parent folder path where the file is going to be created
* @param string $fileName The name of the file to create * @param string $fileName The name of the file to create
* @param string $fileContents The contents of the file to create * @param string $fileContents The contents of the file to create
* @return string Path of the created file
* @throws \Box\Spout\Common\Exception\IOException If unable to create the file or if the file path is not inside of the base folder * @throws \Box\Spout\Common\Exception\IOException If unable to create the file or if the file path is not inside of the base folder
* @return string Path of the created file
*/ */
public function createFileWithContents($parentFolderPath, $fileName, $fileContents) public function createFileWithContents($parentFolderPath, $fileName, $fileContents)
{ {
@ -74,8 +72,8 @@ class FileSystemHelper implements FileSystemHelperInterface
* Delete the file at the given path * Delete the file at the given path
* *
* @param string $filePath Path of the file to delete * @param string $filePath Path of the file to delete
* @return void
* @throws \Box\Spout\Common\Exception\IOException If the file path is not inside of the base folder * @throws \Box\Spout\Common\Exception\IOException If the file path is not inside of the base folder
* @return void
*/ */
public function deleteFile($filePath) public function deleteFile($filePath)
{ {
@ -90,8 +88,8 @@ class FileSystemHelper implements FileSystemHelperInterface
* Delete the folder at the given path as well as all its contents * Delete the folder at the given path as well as all its contents
* *
* @param string $folderPath Path of the folder to delete * @param string $folderPath Path of the folder to delete
* @return void
* @throws \Box\Spout\Common\Exception\IOException If the folder path is not inside of the base folder * @throws \Box\Spout\Common\Exception\IOException If the folder path is not inside of the base folder
* @return void
*/ */
public function deleteFolderRecursively($folderPath) public function deleteFolderRecursively($folderPath)
{ {
@ -119,8 +117,8 @@ class FileSystemHelper implements FileSystemHelperInterface
* should occur is not inside the base folder. * should occur is not inside the base folder.
* *
* @param string $operationFolderPath The path of the folder where the I/O operation should occur * @param string $operationFolderPath The path of the folder where the I/O operation should occur
* @return void
* @throws \Box\Spout\Common\Exception\IOException If the folder where the I/O operation should occur is not inside the base folder * @throws \Box\Spout\Common\Exception\IOException If the folder where the I/O operation should occur is not inside the base folder
* @return void
*/ */
protected function throwIfOperationNotInBaseFolder($operationFolderPath) protected function throwIfOperationNotInBaseFolder($operationFolderPath)
{ {

View File

@ -6,8 +6,6 @@ namespace Box\Spout\Common\Helper;
* Class FileSystemHelperInterface * Class FileSystemHelperInterface
* This interface describes helper functions to help with the file system operations * This interface describes helper functions to help with the file system operations
* like files/folders creation & deletion * like files/folders creation & deletion
*
* @package Box\Spout\Common\Helper
*/ */
interface FileSystemHelperInterface interface FileSystemHelperInterface
{ {
@ -16,8 +14,8 @@ interface FileSystemHelperInterface
* *
* @param string $parentFolderPath The parent folder path under which the folder is going to be created * @param string $parentFolderPath The parent folder path under which the folder is going to be created
* @param string $folderName The name of the folder to create * @param string $folderName The name of the folder to create
* @return string Path of the created folder
* @throws \Box\Spout\Common\Exception\IOException If unable to create the folder or if the folder path is not inside of the base folder * @throws \Box\Spout\Common\Exception\IOException If unable to create the folder or if the folder path is not inside of the base folder
* @return string Path of the created folder
*/ */
public function createFolder($parentFolderPath, $folderName); public function createFolder($parentFolderPath, $folderName);
@ -28,8 +26,8 @@ interface FileSystemHelperInterface
* @param string $parentFolderPath The parent folder path where the file is going to be created * @param string $parentFolderPath The parent folder path where the file is going to be created
* @param string $fileName The name of the file to create * @param string $fileName The name of the file to create
* @param string $fileContents The contents of the file to create * @param string $fileContents The contents of the file to create
* @return string Path of the created file
* @throws \Box\Spout\Common\Exception\IOException If unable to create the file or if the file path is not inside of the base folder * @throws \Box\Spout\Common\Exception\IOException If unable to create the file or if the file path is not inside of the base folder
* @return string Path of the created file
*/ */
public function createFileWithContents($parentFolderPath, $fileName, $fileContents); public function createFileWithContents($parentFolderPath, $fileName, $fileContents);
@ -37,8 +35,8 @@ interface FileSystemHelperInterface
* Delete the file at the given path * Delete the file at the given path
* *
* @param string $filePath Path of the file to delete * @param string $filePath Path of the file to delete
* @return void
* @throws \Box\Spout\Common\Exception\IOException If the file path is not inside of the base folder * @throws \Box\Spout\Common\Exception\IOException If the file path is not inside of the base folder
* @return void
*/ */
public function deleteFile($filePath); public function deleteFile($filePath);
@ -46,8 +44,8 @@ interface FileSystemHelperInterface
* Delete the folder at the given path as well as all its contents * Delete the folder at the given path as well as all its contents
* *
* @param string $folderPath Path of the folder to delete * @param string $folderPath Path of the folder to delete
* @return void
* @throws \Box\Spout\Common\Exception\IOException If the folder path is not inside of the base folder * @throws \Box\Spout\Common\Exception\IOException If the folder path is not inside of the base folder
* @return void
*/ */
public function deleteFolderRecursively($folderPath); public function deleteFolderRecursively($folderPath);
} }

View File

@ -7,8 +7,6 @@ namespace Box\Spout\Common\Helper;
* This class wraps global functions to facilitate testing * This class wraps global functions to facilitate testing
* *
* @codeCoverageIgnore * @codeCoverageIgnore
*
* @package Box\Spout\Common\Helper
*/ */
class GlobalFunctionsHelper class GlobalFunctionsHelper
{ {
@ -30,7 +28,7 @@ class GlobalFunctionsHelper
* @see fgets() * @see fgets()
* *
* @param resource $handle * @param resource $handle
* @param int|void $length * @param int|null $length
* @return string * @return string
*/ */
public function fgets($handle, $length = null) public function fgets($handle, $length = null)
@ -81,9 +79,9 @@ class GlobalFunctionsHelper
* @see fgetcsv() * @see fgetcsv()
* *
* @param resource $handle * @param resource $handle
* @param int|void $length * @param int|null $length
* @param string|void $delimiter * @param string|null $delimiter
* @param string|void $enclosure * @param string|null $enclosure
* @return array * @return array
*/ */
public function fgetcsv($handle, $length = null, $delimiter = null, $enclosure = null) public function fgetcsv($handle, $length = null, $delimiter = null, $enclosure = null)
@ -97,8 +95,8 @@ class GlobalFunctionsHelper
* *
* @param resource $handle * @param resource $handle
* @param array $fields * @param array $fields
* @param string|void $delimiter * @param string|null $delimiter
* @param string|void $enclosure * @param string|null $enclosure
* @return int * @return int
*/ */
public function fputcsv($handle, array $fields, $delimiter = null, $enclosure = null) public function fputcsv($handle, array $fields, $delimiter = null, $enclosure = null)
@ -165,6 +163,7 @@ class GlobalFunctionsHelper
public function file_get_contents($filePath) public function file_get_contents($filePath)
{ {
$realFilePath = $this->convertToUseRealPath($filePath); $realFilePath = $this->convertToUseRealPath($filePath);
return file_get_contents($realFilePath); return file_get_contents($realFilePath);
} }
@ -207,7 +206,7 @@ class GlobalFunctionsHelper
* Wrapper around global function feof() * Wrapper around global function feof()
* @see feof() * @see feof()
* *
* @param resource * @param resource $handle
* @return bool * @return bool
*/ */
public function feof($handle) public function feof($handle)
@ -232,7 +231,7 @@ class GlobalFunctionsHelper
* @see basename() * @see basename()
* *
* @param string $path * @param string $path
* @param string|void $suffix * @param string|null $suffix
* @return string * @return string
*/ */
public function basename($path, $suffix = null) public function basename($path, $suffix = null)

View File

@ -7,8 +7,6 @@ namespace Box\Spout\Common\Helper;
* This class provides helper functions to work with strings and multibyte strings. * This class provides helper functions to work with strings and multibyte strings.
* *
* @codeCoverageIgnore * @codeCoverageIgnore
*
* @package Box\Spout\Common\Helper
*/ */
class StringHelper class StringHelper
{ {
@ -50,6 +48,7 @@ class StringHelper
public function getCharFirstOccurrencePosition($char, $string) public function getCharFirstOccurrencePosition($char, $string)
{ {
$position = $this->hasMbstringSupport ? mb_strpos($string, $char) : strpos($string, $char); $position = $this->hasMbstringSupport ? mb_strpos($string, $char) : strpos($string, $char);
return ($position !== false) ? $position : -1; return ($position !== false) ? $position : -1;
} }
@ -66,6 +65,7 @@ class StringHelper
public function getCharLastOccurrencePosition($char, $string) public function getCharLastOccurrencePosition($char, $string)
{ {
$position = $this->hasMbstringSupport ? mb_strrpos($string, $char) : strrpos($string, $char); $position = $this->hasMbstringSupport ? mb_strrpos($string, $char) : strrpos($string, $char);
return ($position !== false) ? $position : -1; return ($position !== false) ? $position : -1;
} }
} }

View File

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

View File

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

View File

@ -1,41 +0,0 @@
<?php
namespace Box\Spout\Common;
/**
* Class Singleton
* Defines a class as a singleton.
*
* @package Box\Spout\Common
*/
trait Singleton
{
protected static $instance;
/**
* @return static
*/
final public static function getInstance()
{
return isset(static::$instance)
? static::$instance
: static::$instance = new static;
}
/**
* Singleton constructor.
*/
final private function __construct()
{
$this->init();
}
/**
* Initializes the singleton
* @return void
*/
protected function init() {}
final private function __wakeup() {}
final private function __clone() {}
}

View File

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

View File

@ -0,0 +1,40 @@
<?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
*/
class OptionsManager extends OptionsManagerAbstract
{
/**
* {@inheritdoc}
*/
protected function getSupportedOptions()
{
return [
Options::SHOULD_FORMAT_DATES,
Options::SHOULD_PRESERVE_EMPTY_ROWS,
Options::FIELD_DELIMITER,
Options::FIELD_ENCLOSURE,
Options::ENCODING,
];
}
/**
* {@inheritdoc}
*/
protected function setDefaultOptions()
{
$this->setOption(Options::SHOULD_FORMAT_DATES, false);
$this->setOption(Options::SHOULD_PRESERVE_EMPTY_ROWS, false);
$this->setOption(Options::FIELD_DELIMITER, ',');
$this->setOption(Options::FIELD_ENCLOSURE, '"');
$this->setOption(Options::ENCODING, EncodingHelper::ENCODING_UTF8);
}
}

View File

@ -2,16 +2,16 @@
namespace Box\Spout\Reader\CSV; namespace Box\Spout\Reader\CSV;
use Box\Spout\Reader\AbstractReader;
use Box\Spout\Common\Exception\IOException; use Box\Spout\Common\Exception\IOException;
use Box\Spout\Reader\Common\Entity\Options;
use Box\Spout\Reader\CSV\Creator\EntityFactory;
use Box\Spout\Reader\ReaderAbstract;
/** /**
* Class Reader * Class Reader
* This class provides support to read data from a CSV file. * This class provides support to read data from a CSV file.
*
* @package Box\Spout\Reader\CSV
*/ */
class Reader extends AbstractReader class Reader extends ReaderAbstract
{ {
/** @var resource Pointer to the file to be written */ /** @var resource Pointer to the file to be written */
protected $filePointer; protected $filePointer;
@ -22,19 +22,6 @@ class Reader extends AbstractReader
/** @var string Original value for the "auto_detect_line_endings" INI value */ /** @var string Original value for the "auto_detect_line_endings" INI value */
protected $originalAutoDetectLineEndings; protected $originalAutoDetectLineEndings;
/**
* Returns the reader's current options
*
* @return ReaderOptions
*/
protected function getOptions()
{
if (!isset($this->options)) {
$this->options = new ReaderOptions();
}
return $this->options;
}
/** /**
* Sets the field delimiter for the CSV. * Sets the field delimiter for the CSV.
* Needs to be called before opening the reader. * Needs to be called before opening the reader.
@ -44,7 +31,8 @@ class Reader extends AbstractReader
*/ */
public function setFieldDelimiter($fieldDelimiter) public function setFieldDelimiter($fieldDelimiter)
{ {
$this->getOptions()->setFieldDelimiter($fieldDelimiter); $this->optionsManager->setOption(Options::FIELD_DELIMITER, $fieldDelimiter);
return $this; return $this;
} }
@ -57,7 +45,8 @@ class Reader extends AbstractReader
*/ */
public function setFieldEnclosure($fieldEnclosure) public function setFieldEnclosure($fieldEnclosure)
{ {
$this->getOptions()->setFieldEnclosure($fieldEnclosure); $this->optionsManager->setOption(Options::FIELD_ENCLOSURE, $fieldEnclosure);
return $this; return $this;
} }
@ -70,20 +59,8 @@ class Reader extends AbstractReader
*/ */
public function setEncoding($encoding) public function setEncoding($encoding)
{ {
$this->getOptions()->setEncoding($encoding); $this->optionsManager->setOption(Options::ENCODING, $encoding);
return $this;
}
/**
* Sets the EOL for the CSV.
* Needs to be called before opening the reader.
*
* @param string $endOfLineCharacter used to properly get lines from the CSV file.
* @return Reader
*/
public function setEndOfLineCharacter($endOfLineCharacter)
{
$this->getOptions()->setEndOfLineCharacter($endOfLineCharacter);
return $this; return $this;
} }
@ -102,8 +79,8 @@ class Reader extends AbstractReader
* If setEncoding() was not called, it assumes that the file is encoded in UTF-8. * If setEncoding() was not called, it assumes that the file is encoded in UTF-8.
* *
* @param string $filePath Path of the CSV file to be read * @param string $filePath Path of the CSV file to be read
* @return void
* @throws \Box\Spout\Common\Exception\IOException * @throws \Box\Spout\Common\Exception\IOException
* @return void
*/ */
protected function openReader($filePath) protected function openReader($filePath)
{ {
@ -115,9 +92,12 @@ class Reader extends AbstractReader
throw new IOException("Could not open file $filePath for reading."); throw new IOException("Could not open file $filePath for reading.");
} }
$this->sheetIterator = new SheetIterator( /** @var EntityFactory $entityFactory */
$entityFactory = $this->entityFactory;
$this->sheetIterator = $entityFactory->createSheetIterator(
$this->filePointer, $this->filePointer,
$this->getOptions(), $this->optionsManager,
$this->globalFunctionsHelper $this->globalFunctionsHelper
); );
} }
@ -132,7 +112,6 @@ class Reader extends AbstractReader
return $this->sheetIterator; return $this->sheetIterator;
} }
/** /**
* Closes the reader. To be used after reading the file. * Closes the reader. To be used after reading the file.
* *

View File

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

View File

@ -2,14 +2,13 @@
namespace Box\Spout\Reader\CSV; namespace Box\Spout\Reader\CSV;
use Box\Spout\Reader\IteratorInterface;
use Box\Spout\Common\Helper\EncodingHelper; use Box\Spout\Common\Helper\EncodingHelper;
use Box\Spout\Reader\Common\Entity\Options;
use Box\Spout\Reader\IteratorInterface;
/** /**
* Class RowIterator * Class RowIterator
* Iterate over CSV rows. * Iterate over CSV rows.
*
* @package Box\Spout\Reader\CSV
*/ */
class RowIterator implements IteratorInterface class RowIterator implements IteratorInterface
{ {
@ -25,7 +24,7 @@ class RowIterator implements IteratorInterface
protected $numReadRows = 0; protected $numReadRows = 0;
/** @var array|null Buffer used to store the row data, while checking if there are more rows to read */ /** @var array|null Buffer used to store the row data, while checking if there are more rows to read */
protected $rowDataBuffer = null; protected $rowDataBuffer;
/** @var bool Indicates whether all rows have been read */ /** @var bool Indicates whether all rows have been read */
protected $hasReachedEndOfFile = false; protected $hasReachedEndOfFile = false;
@ -39,9 +38,6 @@ class RowIterator implements IteratorInterface
/** @var string Encoding of the CSV file to be read */ /** @var string Encoding of the CSV file to be read */
protected $encoding; protected $encoding;
/** @var string End of line delimiter, given by the user as input. */
protected $inputEOLDelimiter;
/** @var bool Whether empty rows should be returned or skipped */ /** @var bool Whether empty rows should be returned or skipped */
protected $shouldPreserveEmptyRows; protected $shouldPreserveEmptyRows;
@ -51,30 +47,26 @@ class RowIterator implements IteratorInterface
/** @var \Box\Spout\Common\Helper\EncodingHelper Helper to work with different encodings */ /** @var \Box\Spout\Common\Helper\EncodingHelper Helper to work with different encodings */
protected $encodingHelper; protected $encodingHelper;
/** @var string End of line delimiter, encoded using the same encoding as the CSV */
protected $encodedEOLDelimiter;
/** /**
* @param resource $filePointer Pointer to the CSV file to read * @param resource $filePointer Pointer to the CSV file to read
* @param \Box\Spout\Reader\CSV\ReaderOptions $options * @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager
* @param \Box\Spout\Common\Helper\EncodingHelper $encodingHelper
* @param \Box\Spout\Common\Helper\GlobalFunctionsHelper $globalFunctionsHelper * @param \Box\Spout\Common\Helper\GlobalFunctionsHelper $globalFunctionsHelper
*/ */
public function __construct($filePointer, $options, $globalFunctionsHelper) public function __construct($filePointer, $optionsManager, $encodingHelper, $globalFunctionsHelper)
{ {
$this->filePointer = $filePointer; $this->filePointer = $filePointer;
$this->fieldDelimiter = $options->getFieldDelimiter(); $this->fieldDelimiter = $optionsManager->getOption(Options::FIELD_DELIMITER);
$this->fieldEnclosure = $options->getFieldEnclosure(); $this->fieldEnclosure = $optionsManager->getOption(Options::FIELD_ENCLOSURE);
$this->encoding = $options->getEncoding(); $this->encoding = $optionsManager->getOption(Options::ENCODING);
$this->inputEOLDelimiter = $options->getEndOfLineCharacter(); $this->shouldPreserveEmptyRows = $optionsManager->getOption(Options::SHOULD_PRESERVE_EMPTY_ROWS);
$this->shouldPreserveEmptyRows = $options->shouldPreserveEmptyRows(); $this->encodingHelper = $encodingHelper;
$this->globalFunctionsHelper = $globalFunctionsHelper; $this->globalFunctionsHelper = $globalFunctionsHelper;
$this->encodingHelper = new EncodingHelper($globalFunctionsHelper);
} }
/** /**
* Rewind the Iterator to the first element * Rewind the Iterator to the first element
* @link http://php.net/manual/en/iterator.rewind.php * @see http://php.net/manual/en/iterator.rewind.php
* *
* @return void * @return void
*/ */
@ -104,7 +96,7 @@ class RowIterator implements IteratorInterface
/** /**
* Checks if current position is valid * Checks if current position is valid
* @link http://php.net/manual/en/iterator.valid.php * @see http://php.net/manual/en/iterator.valid.php
* *
* @return bool * @return bool
*/ */
@ -115,10 +107,10 @@ class RowIterator implements IteratorInterface
/** /**
* Move forward to next element. Reads data for the next unprocessed row. * Move forward to next element. Reads data for the next unprocessed row.
* @link http://php.net/manual/en/iterator.next.php * @see http://php.net/manual/en/iterator.next.php
* *
* @return void
* @throws \Box\Spout\Common\Exception\EncodingConversionException If unable to convert data to UTF-8 * @throws \Box\Spout\Common\Exception\EncodingConversionException If unable to convert data to UTF-8
* @return void
*/ */
public function next() public function next()
{ {
@ -130,8 +122,8 @@ class RowIterator implements IteratorInterface
} }
/** /**
* @return void
* @throws \Box\Spout\Common\Exception\EncodingConversionException If unable to convert data to UTF-8 * @throws \Box\Spout\Common\Exception\EncodingConversionException If unable to convert data to UTF-8
* @return void
*/ */
protected function readDataForNextRow() protected function readDataForNextRow()
{ {
@ -171,8 +163,8 @@ class RowIterator implements IteratorInterface
* As fgetcsv() does not manage correctly encoding for non UTF-8 data, * As fgetcsv() does not manage correctly encoding for non UTF-8 data,
* we remove manually whitespace with ltrim or rtrim (depending on the order of the bytes) * we remove manually whitespace with ltrim or rtrim (depending on the order of the bytes)
* *
* @return array|false The row for the current file pointer, encoded in UTF-8 or FALSE if nothing to read
* @throws \Box\Spout\Common\Exception\EncodingConversionException If unable to convert data to UTF-8 * @throws \Box\Spout\Common\Exception\EncodingConversionException If unable to convert data to UTF-8
* @return array|false The row for the current file pointer, encoded in UTF-8 or FALSE if nothing to read
*/ */
protected function getNextUTF8EncodedRow() protected function getNextUTF8EncodedRow()
{ {
@ -202,21 +194,6 @@ class RowIterator implements IteratorInterface
return $encodedRowData; return $encodedRowData;
} }
/**
* Returns the end of line delimiter, encoded using the same encoding as the CSV.
* The return value is cached.
*
* @return string
*/
protected function getEncodedEOLDelimiter()
{
if (!isset($this->encodedEOLDelimiter)) {
$this->encodedEOLDelimiter = $this->encodingHelper->attemptConversionFromUTF8($this->inputEOLDelimiter, $this->encoding);
}
return $this->encodedEOLDelimiter;
}
/** /**
* @param array|bool $lineData Array containing the cells value for the line * @param array|bool $lineData Array containing the cells value for the line
* @return bool Whether the given line is empty * @return bool Whether the given line is empty
@ -228,7 +205,7 @@ class RowIterator implements IteratorInterface
/** /**
* Return the current element from the buffer * Return the current element from the buffer
* @link http://php.net/manual/en/iterator.current.php * @see http://php.net/manual/en/iterator.current.php
* *
* @return array|null * @return array|null
*/ */
@ -239,7 +216,7 @@ class RowIterator implements IteratorInterface
/** /**
* Return the key of the current element * Return the key of the current element
* @link http://php.net/manual/en/iterator.key.php * @see http://php.net/manual/en/iterator.key.php
* *
* @return int * @return int
*/ */

View File

@ -6,8 +6,6 @@ use Box\Spout\Reader\SheetInterface;
/** /**
* Class Sheet * Class Sheet
*
* @package Box\Spout\Reader\CSV
*/ */
class Sheet implements SheetInterface class Sheet implements SheetInterface
{ {
@ -15,13 +13,11 @@ class Sheet implements SheetInterface
protected $rowIterator; protected $rowIterator;
/** /**
* @param resource $filePointer Pointer to the CSV file to read * @param RowIterator $rowIterator Corresponding row iterator
* @param \Box\Spout\Reader\CSV\ReaderOptions $options
* @param \Box\Spout\Common\Helper\GlobalFunctionsHelper $globalFunctionsHelper
*/ */
public function __construct($filePointer, $options, $globalFunctionsHelper) public function __construct(RowIterator $rowIterator)
{ {
$this->rowIterator = new RowIterator($filePointer, $options, $globalFunctionsHelper); $this->rowIterator = $rowIterator;
} }
/** /**

View File

@ -7,8 +7,6 @@ use Box\Spout\Reader\IteratorInterface;
/** /**
* Class SheetIterator * Class SheetIterator
* Iterate over CSV unique "sheet". * Iterate over CSV unique "sheet".
*
* @package Box\Spout\Reader\CSV
*/ */
class SheetIterator implements IteratorInterface class SheetIterator implements IteratorInterface
{ {
@ -19,18 +17,16 @@ class SheetIterator implements IteratorInterface
protected $hasReadUniqueSheet = false; protected $hasReadUniqueSheet = false;
/** /**
* @param resource $filePointer * @param Sheet $sheet Corresponding unique sheet
* @param \Box\Spout\Reader\CSV\ReaderOptions $options
* @param \Box\Spout\Common\Helper\GlobalFunctionsHelper $globalFunctionsHelper
*/ */
public function __construct($filePointer, $options, $globalFunctionsHelper) public function __construct($sheet)
{ {
$this->sheet = new Sheet($filePointer, $options, $globalFunctionsHelper); $this->sheet = $sheet;
} }
/** /**
* Rewind the Iterator to the first element * Rewind the Iterator to the first element
* @link http://php.net/manual/en/iterator.rewind.php * @see http://php.net/manual/en/iterator.rewind.php
* *
* @return void * @return void
*/ */
@ -41,7 +37,7 @@ class SheetIterator implements IteratorInterface
/** /**
* Checks if current position is valid * Checks if current position is valid
* @link http://php.net/manual/en/iterator.valid.php * @see http://php.net/manual/en/iterator.valid.php
* *
* @return bool * @return bool
*/ */
@ -52,7 +48,7 @@ class SheetIterator implements IteratorInterface
/** /**
* Move forward to next element * Move forward to next element
* @link http://php.net/manual/en/iterator.next.php * @see http://php.net/manual/en/iterator.next.php
* *
* @return void * @return void
*/ */
@ -63,7 +59,7 @@ class SheetIterator implements IteratorInterface
/** /**
* Return the current element * Return the current element
* @link http://php.net/manual/en/iterator.current.php * @see http://php.net/manual/en/iterator.current.php
* *
* @return \Box\Spout\Reader\CSV\Sheet * @return \Box\Spout\Reader\CSV\Sheet
*/ */
@ -74,7 +70,7 @@ class SheetIterator implements IteratorInterface
/** /**
* Return the key of the current element * Return the key of the current element
* @link http://php.net/manual/en/iterator.key.php * @see http://php.net/manual/en/iterator.key.php
* *
* @return int * @return int
*/ */

View File

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

View File

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

View File

@ -5,8 +5,6 @@ namespace Box\Spout\Reader\Common;
/** /**
* Class ReaderOptions * Class ReaderOptions
* Readers' common options * Readers' common options
*
* @package Box\Spout\Reader\Common
*/ */
class ReaderOptions class ReaderOptions
{ {
@ -33,6 +31,7 @@ class ReaderOptions
public function setShouldFormatDates($shouldFormatDates) public function setShouldFormatDates($shouldFormatDates)
{ {
$this->shouldFormatDates = $shouldFormatDates; $this->shouldFormatDates = $shouldFormatDates;
return $this; return $this;
} }
@ -53,6 +52,7 @@ class ReaderOptions
public function setShouldPreserveEmptyRows($shouldPreserveEmptyRows) public function setShouldPreserveEmptyRows($shouldPreserveEmptyRows)
{ {
$this->shouldPreserveEmptyRows = $shouldPreserveEmptyRows; $this->shouldPreserveEmptyRows = $shouldPreserveEmptyRows;
return $this; return $this;
} }
} }

View File

@ -7,8 +7,6 @@ use Box\Spout\Reader\Wrapper\XMLReader;
/** /**
* Class XMLProcessor * Class XMLProcessor
* Helps process XML files * Helps process XML files
*
* @package Box\Spout\Reader\Common
*/ */
class XMLProcessor class XMLProcessor
{ {
@ -24,14 +22,12 @@ class XMLProcessor
const PROCESSING_CONTINUE = 1; const PROCESSING_CONTINUE = 1;
const PROCESSING_STOP = 2; const PROCESSING_STOP = 2;
/** @var \Box\Spout\Reader\Wrapper\XMLReader The XMLReader object that will help read sheet's XML data */ /** @var \Box\Spout\Reader\Wrapper\XMLReader The XMLReader object that will help read sheet's XML data */
protected $xmlReader; protected $xmlReader;
/** @var array Registered callbacks */ /** @var array Registered callbacks */
private $callbacks = []; private $callbacks = [];
/** /**
* @param \Box\Spout\Reader\Wrapper\XMLReader $xmlReader XMLReader object * @param \Box\Spout\Reader\Wrapper\XMLReader $xmlReader XMLReader object
*/ */
@ -90,8 +86,8 @@ class XMLProcessor
* Resumes the reading of the XML file where it was left off. * Resumes the reading of the XML file where it was left off.
* Stops whenever a callback indicates that reading should stop or at the end of the file. * Stops whenever a callback indicates that reading should stop or at the end of the file.
* *
* @return void
* @throws \Box\Spout\Reader\Exception\XMLProcessingException * @throws \Box\Spout\Reader\Exception\XMLProcessingException
* @return void
*/ */
public function readUntilStopped() public function readUntilStopped()
{ {

View File

@ -6,7 +6,6 @@ namespace Box\Spout\Reader\Exception;
* Class IteratorNotRewindableException * Class IteratorNotRewindableException
* *
* @api * @api
* @package Box\Spout\Reader\Exception
*/ */
class IteratorNotRewindableException extends ReaderException class IteratorNotRewindableException extends ReaderException
{ {

View File

@ -6,7 +6,6 @@ namespace Box\Spout\Reader\Exception;
* Class NoSheetsFoundException * Class NoSheetsFoundException
* *
* @api * @api
* @package Box\Spout\Reader\Exception
*/ */
class NoSheetsFoundException extends ReaderException class NoSheetsFoundException extends ReaderException
{ {

View File

@ -7,7 +7,6 @@ use Box\Spout\Common\Exception\SpoutException;
/** /**
* Class ReaderException * Class ReaderException
* *
* @package Box\Spout\Reader\Exception
* @abstract * @abstract
*/ */
abstract class ReaderException extends SpoutException abstract class ReaderException extends SpoutException

View File

@ -6,7 +6,6 @@ namespace Box\Spout\Reader\Exception;
* Class ReaderNotOpenedException * Class ReaderNotOpenedException
* *
* @api * @api
* @package Box\Spout\Reader\Exception
*/ */
class ReaderNotOpenedException extends ReaderException class ReaderNotOpenedException extends ReaderException
{ {

View File

@ -6,7 +6,6 @@ namespace Box\Spout\Reader\Exception;
* Class SharedStringNotFoundException * Class SharedStringNotFoundException
* *
* @api * @api
* @package Box\Spout\Reader\Exception
*/ */
class SharedStringNotFoundException extends ReaderException class SharedStringNotFoundException extends ReaderException
{ {

View File

@ -4,8 +4,6 @@ namespace Box\Spout\Reader\Exception;
/** /**
* Class XMLProcessingException * Class XMLProcessingException
*
* @package Box\Spout\Reader\Exception
*/ */
class XMLProcessingException extends ReaderException class XMLProcessingException extends ReaderException
{ {

View File

@ -4,8 +4,6 @@ namespace Box\Spout\Reader;
/** /**
* Interface IteratorInterface * Interface IteratorInterface
*
* @package Box\Spout\Reader
*/ */
interface IteratorInterface extends \Iterator interface IteratorInterface extends \Iterator
{ {

View File

@ -0,0 +1,96 @@
<?php
namespace Box\Spout\Reader\ODS\Creator;
use Box\Spout\Reader\Common\Creator\EntityFactoryInterface;
use Box\Spout\Reader\Common\Entity\Options;
use Box\Spout\Reader\Common\XMLProcessor;
use Box\Spout\Reader\ODS\RowIterator;
use Box\Spout\Reader\ODS\Sheet;
use Box\Spout\Reader\ODS\SheetIterator;
use Box\Spout\Reader\Wrapper\XMLReader;
/**
* Class EntityFactory
* Factory to create entities
*/
class EntityFactory implements EntityFactoryInterface
{
/** @var HelperFactory */
private $helperFactory;
/**
* @param HelperFactory $helperFactory
*/
public function __construct(HelperFactory $helperFactory)
{
$this->helperFactory = $helperFactory;
}
/**
* @param string $filePath Path of the file to be read
* @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager Reader's options manager
* @return SheetIterator
*/
public function createSheetIterator($filePath, $optionsManager)
{
$escaper = $this->helperFactory->createStringsEscaper();
$settingsHelper = $this->helperFactory->createSettingsHelper($this);
return new SheetIterator($filePath, $optionsManager, $escaper, $settingsHelper, $this);
}
/**
* @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)
{
$rowIterator = $this->createRowIterator($xmlReader, $optionsManager);
return new Sheet($rowIterator, $sheetIndex, $sheetName, $isSheetActive);
}
/**
* @param XMLReader $xmlReader XML Reader
* @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager Reader's options manager
* @return RowIterator
*/
private function createRowIterator($xmlReader, $optionsManager)
{
$shouldFormatDates = $optionsManager->getOption(Options::SHOULD_FORMAT_DATES);
$cellValueFormatter = $this->helperFactory->createCellValueFormatter($shouldFormatDates);
$xmlProcessor = $this->createXMLProcessor($xmlReader);
return new RowIterator($xmlReader, $optionsManager, $cellValueFormatter, $xmlProcessor);
}
/**
* @return XMLReader
*/
public function createXMLReader()
{
return new XMLReader();
}
/**
* @param $xmlReader
* @return XMLProcessor
*/
private function createXMLProcessor($xmlReader)
{
return new XMLProcessor($xmlReader);
}
/**
* @return \ZipArchive
*/
public function createZipArchive()
{
return new \ZipArchive();
}
}

View File

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

View File

@ -5,8 +5,6 @@ namespace Box\Spout\Reader\ODS\Helper;
/** /**
* Class CellValueFormatter * Class CellValueFormatter
* This class provides helper functions to format cell values * This class provides helper functions to format cell values
*
* @package Box\Spout\Reader\ODS\Helper
*/ */
class CellValueFormatter class CellValueFormatter
{ {
@ -38,18 +36,17 @@ class CellValueFormatter
/** @var bool Whether date/time values should be returned as PHP objects or be formatted as strings */ /** @var bool Whether date/time values should be returned as PHP objects or be formatted as strings */
protected $shouldFormatDates; protected $shouldFormatDates;
/** @var \Box\Spout\Common\Escaper\ODS Used to unescape XML data */ /** @var \Box\Spout\Common\Helper\Escaper\ODS Used to unescape XML data */
protected $escaper; protected $escaper;
/** /**
* @param bool $shouldFormatDates Whether date/time values should be returned as PHP objects or be formatted as strings * @param bool $shouldFormatDates Whether date/time values should be returned as PHP objects or be formatted as strings
* @param \Box\Spout\Common\Helper\Escaper\ODS $escaper Used to unescape XML data
*/ */
public function __construct($shouldFormatDates) public function __construct($shouldFormatDates, $escaper)
{ {
$this->shouldFormatDates = $shouldFormatDates; $this->shouldFormatDates = $shouldFormatDates;
$this->escaper = $escaper;
/** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */
$this->escaper = \Box\Spout\Common\Escaper\ODS::getInstance();
} }
/** /**
@ -103,7 +100,7 @@ class CellValueFormatter
$currentPValue .= $childNode->nodeValue; $currentPValue .= $childNode->nodeValue;
} elseif ($childNode->nodeName === self::XML_NODE_S) { } elseif ($childNode->nodeName === self::XML_NODE_S) {
$spaceAttribute = $childNode->getAttribute(self::XML_ATTRIBUTE_C); $spaceAttribute = $childNode->getAttribute(self::XML_ATTRIBUTE_C);
$numSpaces = (!empty($spaceAttribute)) ? intval($spaceAttribute) : 1; $numSpaces = (!empty($spaceAttribute)) ? (int) $spaceAttribute : 1;
$currentPValue .= str_repeat(' ', $numSpaces); $currentPValue .= str_repeat(' ', $numSpaces);
} elseif ($childNode->nodeName === self::XML_NODE_A || $childNode->nodeName === self::XML_NODE_SPAN) { } elseif ($childNode->nodeName === self::XML_NODE_A || $childNode->nodeName === self::XML_NODE_SPAN) {
$currentPValue .= $childNode->nodeValue; $currentPValue .= $childNode->nodeValue;
@ -115,6 +112,7 @@ class CellValueFormatter
$escapedCellValue = implode("\n", $pNodeValues); $escapedCellValue = implode("\n", $pNodeValues);
$cellValue = $this->escaper->unescape($escapedCellValue); $cellValue = $this->escaper->unescape($escapedCellValue);
return $cellValue; return $cellValue;
} }
@ -127,9 +125,11 @@ class CellValueFormatter
protected function formatFloatCellValue($node) protected function formatFloatCellValue($node)
{ {
$nodeValue = $node->getAttribute(self::XML_ATTRIBUTE_VALUE); $nodeValue = $node->getAttribute(self::XML_ATTRIBUTE_VALUE);
$nodeIntValue = intval($nodeValue);
// The "==" is intentionally not a "===" because only the value matters, not the type $nodeIntValue = (int) $nodeValue;
$cellValue = ($nodeIntValue == $nodeValue) ? $nodeIntValue : floatval($nodeValue); $nodeFloatValue = (float) $nodeValue;
$cellValue = ((float) $nodeIntValue === $nodeFloatValue) ? $nodeIntValue : $nodeFloatValue;
return $cellValue; return $cellValue;
} }
@ -142,9 +142,8 @@ class CellValueFormatter
protected function formatBooleanCellValue($node) protected function formatBooleanCellValue($node)
{ {
$nodeValue = $node->getAttribute(self::XML_ATTRIBUTE_BOOLEAN_VALUE); $nodeValue = $node->getAttribute(self::XML_ATTRIBUTE_BOOLEAN_VALUE);
// !! is similar to boolval()
$cellValue = !!$nodeValue; return (bool) $nodeValue;
return $cellValue;
} }
/** /**
@ -163,16 +162,18 @@ class CellValueFormatter
if ($this->shouldFormatDates) { if ($this->shouldFormatDates) {
// The date is already formatted in the "p" tag // The date is already formatted in the "p" tag
$nodeWithValueAlreadyFormatted = $node->getElementsByTagName(self::XML_NODE_P)->item(0); $nodeWithValueAlreadyFormatted = $node->getElementsByTagName(self::XML_NODE_P)->item(0);
return $nodeWithValueAlreadyFormatted->nodeValue; $cellValue = $nodeWithValueAlreadyFormatted->nodeValue;
} else { } else {
// otherwise, get it from the "date-value" attribute // otherwise, get it from the "date-value" attribute
try { try {
$nodeValue = $node->getAttribute(self::XML_ATTRIBUTE_DATE_VALUE); $nodeValue = $node->getAttribute(self::XML_ATTRIBUTE_DATE_VALUE);
return new \DateTime($nodeValue); $cellValue = new \DateTime($nodeValue);
} catch (\Exception $e) { } catch (\Exception $e) {
return null; $cellValue = null;
} }
} }
return $cellValue;
} }
/** /**
@ -191,16 +192,18 @@ class CellValueFormatter
if ($this->shouldFormatDates) { if ($this->shouldFormatDates) {
// The date is already formatted in the "p" tag // The date is already formatted in the "p" tag
$nodeWithValueAlreadyFormatted = $node->getElementsByTagName(self::XML_NODE_P)->item(0); $nodeWithValueAlreadyFormatted = $node->getElementsByTagName(self::XML_NODE_P)->item(0);
return $nodeWithValueAlreadyFormatted->nodeValue; $cellValue = $nodeWithValueAlreadyFormatted->nodeValue;
} else { } else {
// otherwise, get it from the "time-value" attribute // otherwise, get it from the "time-value" attribute
try { try {
$nodeValue = $node->getAttribute(self::XML_ATTRIBUTE_TIME_VALUE); $nodeValue = $node->getAttribute(self::XML_ATTRIBUTE_TIME_VALUE);
return new \DateInterval($nodeValue); $cellValue = new \DateInterval($nodeValue);
} catch (\Exception $e) { } catch (\Exception $e) {
return null; $cellValue = null;
} }
} }
return $cellValue;
} }
/** /**

View File

@ -3,13 +3,11 @@
namespace Box\Spout\Reader\ODS\Helper; namespace Box\Spout\Reader\ODS\Helper;
use Box\Spout\Reader\Exception\XMLProcessingException; use Box\Spout\Reader\Exception\XMLProcessingException;
use Box\Spout\Reader\Wrapper\XMLReader; use Box\Spout\Reader\ODS\Creator\EntityFactory;
/** /**
* Class SettingsHelper * Class SettingsHelper
* This class provides helper functions to extract data from the "settings.xml" file. * This class provides helper functions to extract data from the "settings.xml" file.
*
* @package Box\Spout\Reader\ODS\Helper
*/ */
class SettingsHelper class SettingsHelper
{ {
@ -20,13 +18,24 @@ class SettingsHelper
const XML_ATTRIBUTE_CONFIG_NAME = 'config:name'; const XML_ATTRIBUTE_CONFIG_NAME = 'config:name';
const XML_ATTRIBUTE_VALUE_ACTIVE_TABLE = 'ActiveTable'; const XML_ATTRIBUTE_VALUE_ACTIVE_TABLE = 'ActiveTable';
/** @var EntityFactory Factory to create entities */
private $entityFactory;
/**
* @param EntityFactory $entityFactory Factory to create entities
*/
public function __construct($entityFactory)
{
$this->entityFactory = $entityFactory;
}
/** /**
* @param string $filePath Path of the file to be read * @param string $filePath Path of the file to be read
* @return string|null Name of the sheet that was defined as active or NULL if none found * @return string|null Name of the sheet that was defined as active or NULL if none found
*/ */
public function getActiveSheetName($filePath) public function getActiveSheetName($filePath)
{ {
$xmlReader = new XMLReader(); $xmlReader = $this->entityFactory->createXMLReader();
if ($xmlReader->openFileInZip($filePath, self::SETTINGS_XML_FILE_PATH) === false) { if ($xmlReader->openFileInZip($filePath, self::SETTINGS_XML_FILE_PATH) === false) {
return null; return null;
} }

View File

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

View File

@ -3,15 +3,14 @@
namespace Box\Spout\Reader\ODS; namespace Box\Spout\Reader\ODS;
use Box\Spout\Common\Exception\IOException; use Box\Spout\Common\Exception\IOException;
use Box\Spout\Reader\AbstractReader; use Box\Spout\Reader\ODS\Creator\EntityFactory;
use Box\Spout\Reader\ReaderAbstract;
/** /**
* Class Reader * Class Reader
* This class provides support to read data from a ODS file * This class provides support to read data from a ODS file
*
* @package Box\Spout\Reader\ODS
*/ */
class Reader extends AbstractReader class Reader extends ReaderAbstract
{ {
/** @var \ZipArchive */ /** @var \ZipArchive */
protected $zip; protected $zip;
@ -19,19 +18,6 @@ class Reader extends AbstractReader
/** @var SheetIterator To iterator over the ODS sheets */ /** @var SheetIterator To iterator over the ODS sheets */
protected $sheetIterator; protected $sheetIterator;
/**
* Returns the reader's current options
*
* @return ReaderOptions
*/
protected function getOptions()
{
if (!isset($this->options)) {
$this->options = new ReaderOptions();
}
return $this->options;
}
/** /**
* Returns whether stream wrappers are supported * Returns whether stream wrappers are supported
* *
@ -46,16 +32,21 @@ class Reader extends AbstractReader
* Opens the file at the given file path to make it ready to be read. * Opens the file at the given file path to make it ready to be read.
* *
* @param string $filePath Path of the file to be read * @param string $filePath Path of the file to be read
* @return void
* @throws \Box\Spout\Common\Exception\IOException If the file at the given path or its content cannot be read * @throws \Box\Spout\Common\Exception\IOException If the file at the given path or its content cannot be read
* @throws \Box\Spout\Reader\Exception\NoSheetsFoundException If there are no sheets in the file * @throws \Box\Spout\Reader\Exception\NoSheetsFoundException If there are no sheets in the file
* @return void
*/ */
protected function openReader($filePath) protected function openReader($filePath)
{ {
$this->zip = new \ZipArchive(); /** @var EntityFactory $entityFactory */
$entityFactory = $this->entityFactory;
$this->zip = $entityFactory->createZipArchive();
if ($this->zip->open($filePath) === true) { if ($this->zip->open($filePath) === true) {
$this->sheetIterator = new SheetIterator($filePath, $this->getOptions()); /** @var EntityFactory $entityFactory */
$entityFactory = $this->entityFactory;
$this->sheetIterator = $entityFactory->createSheetIterator($filePath, $this->optionsManager);
} else { } else {
throw new IOException("Could not open $filePath for reading."); throw new IOException("Could not open $filePath for reading.");
} }

View File

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

View File

@ -3,17 +3,16 @@
namespace Box\Spout\Reader\ODS; namespace Box\Spout\Reader\ODS;
use Box\Spout\Common\Exception\IOException; use Box\Spout\Common\Exception\IOException;
use Box\Spout\Reader\Common\Entity\Options;
use Box\Spout\Reader\Common\XMLProcessor;
use Box\Spout\Reader\Exception\IteratorNotRewindableException; use Box\Spout\Reader\Exception\IteratorNotRewindableException;
use Box\Spout\Reader\Exception\XMLProcessingException; use Box\Spout\Reader\Exception\XMLProcessingException;
use Box\Spout\Reader\IteratorInterface; use Box\Spout\Reader\IteratorInterface;
use Box\Spout\Reader\ODS\Helper\CellValueFormatter; use Box\Spout\Reader\ODS\Helper\CellValueFormatter;
use Box\Spout\Reader\Wrapper\XMLReader; use Box\Spout\Reader\Wrapper\XMLReader;
use Box\Spout\Reader\Common\XMLProcessor;
/** /**
* Class RowIterator * Class RowIterator
*
* @package Box\Spout\Reader\ODS
*/ */
class RowIterator implements IteratorInterface class RowIterator implements IteratorInterface
{ {
@ -46,7 +45,7 @@ class RowIterator implements IteratorInterface
protected $currentlyProcessedRowData = []; protected $currentlyProcessedRowData = [];
/** @var array|null Buffer used to store the row data, while checking if there are more rows to read */ /** @var array|null Buffer used to store the row data, while checking if there are more rows to read */
protected $rowDataBuffer = null; protected $rowDataBuffer;
/** @var bool Indicates whether all rows have been read */ /** @var bool Indicates whether all rows have been read */
protected $hasReachedEndOfFile = false; protected $hasReachedEndOfFile = false;
@ -58,7 +57,7 @@ class RowIterator implements IteratorInterface
protected $nextRowIndexToBeProcessed = 1; protected $nextRowIndexToBeProcessed = 1;
/** @var mixed|null Value of the last processed cell (because when reading cell at column N+1, cell N is processed) */ /** @var mixed|null Value of the last processed cell (because when reading cell at column N+1, cell N is processed) */
protected $lastProcessedCellValue = null; protected $lastProcessedCellValue;
/** @var int Number of times the last processed row should be repeated */ /** @var int Number of times the last processed row should be repeated */
protected $numRowsRepeated = 1; protected $numRowsRepeated = 1;
@ -69,19 +68,20 @@ class RowIterator implements IteratorInterface
/** @var bool Whether at least one cell has been read for the row currently being processed */ /** @var bool Whether at least one cell has been read for the row currently being processed */
protected $hasAlreadyReadOneCellInCurrentRow = false; protected $hasAlreadyReadOneCellInCurrentRow = false;
/** /**
* @param XMLReader $xmlReader XML Reader, positioned on the "<table:table>" element * @param XMLReader $xmlReader XML Reader, positioned on the "<table:table>" element
* @param \Box\Spout\Reader\ODS\ReaderOptions $options Reader's current options * @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager Reader's options manager
* @param CellValueFormatter $cellValueFormatter Helper to format cell values
* @param XMLProcessor $xmlProcessor Helper to process XML files
*/ */
public function __construct($xmlReader, $options) public function __construct($xmlReader, $optionsManager, $cellValueFormatter, $xmlProcessor)
{ {
$this->xmlReader = $xmlReader; $this->xmlReader = $xmlReader;
$this->shouldPreserveEmptyRows = $options->shouldPreserveEmptyRows(); $this->shouldPreserveEmptyRows = $optionsManager->getOption(Options::SHOULD_PRESERVE_EMPTY_ROWS);
$this->cellValueFormatter = new CellValueFormatter($options->shouldFormatDates()); $this->cellValueFormatter = $cellValueFormatter;
// Register all callbacks to process different nodes when reading the XML file // Register all callbacks to process different nodes when reading the XML file
$this->xmlProcessor = new XMLProcessor($this->xmlReader); $this->xmlProcessor = $xmlProcessor;
$this->xmlProcessor->registerCallback(self::XML_NODE_ROW, XMLProcessor::NODE_TYPE_START, [$this, 'processRowStartingNode']); $this->xmlProcessor->registerCallback(self::XML_NODE_ROW, XMLProcessor::NODE_TYPE_START, [$this, 'processRowStartingNode']);
$this->xmlProcessor->registerCallback(self::XML_NODE_CELL, XMLProcessor::NODE_TYPE_START, [$this, 'processCellStartingNode']); $this->xmlProcessor->registerCallback(self::XML_NODE_CELL, XMLProcessor::NODE_TYPE_START, [$this, 'processCellStartingNode']);
$this->xmlProcessor->registerCallback(self::XML_NODE_ROW, XMLProcessor::NODE_TYPE_END, [$this, 'processRowEndingNode']); $this->xmlProcessor->registerCallback(self::XML_NODE_ROW, XMLProcessor::NODE_TYPE_END, [$this, 'processRowEndingNode']);
@ -91,10 +91,10 @@ class RowIterator implements IteratorInterface
/** /**
* Rewind the Iterator to the first element. * Rewind the Iterator to the first element.
* NOTE: It can only be done once, as it is not possible to read an XML file backwards. * NOTE: It can only be done once, as it is not possible to read an XML file backwards.
* @link http://php.net/manual/en/iterator.rewind.php * @see http://php.net/manual/en/iterator.rewind.php
* *
* @return void
* @throws \Box\Spout\Reader\Exception\IteratorNotRewindableException If the iterator is rewound more than once * @throws \Box\Spout\Reader\Exception\IteratorNotRewindableException If the iterator is rewound more than once
* @return void
*/ */
public function rewind() public function rewind()
{ {
@ -116,7 +116,7 @@ class RowIterator implements IteratorInterface
/** /**
* Checks if current position is valid * Checks if current position is valid
* @link http://php.net/manual/en/iterator.valid.php * @see http://php.net/manual/en/iterator.valid.php
* *
* @return bool * @return bool
*/ */
@ -127,11 +127,11 @@ class RowIterator implements IteratorInterface
/** /**
* Move forward to next element. Empty rows will be skipped. * Move forward to next element. Empty rows will be skipped.
* @link http://php.net/manual/en/iterator.next.php * @see http://php.net/manual/en/iterator.next.php
* *
* @return void
* @throws \Box\Spout\Reader\Exception\SharedStringNotFoundException If a shared string was not found * @throws \Box\Spout\Reader\Exception\SharedStringNotFoundException If a shared string was not found
* @throws \Box\Spout\Common\Exception\IOException If unable to read the sheet data XML * @throws \Box\Spout\Common\Exception\IOException If unable to read the sheet data XML
* @return void
*/ */
public function next() public function next()
{ {
@ -162,9 +162,9 @@ class RowIterator implements IteratorInterface
} }
/** /**
* @return void
* @throws \Box\Spout\Reader\Exception\SharedStringNotFoundException If a shared string was not found * @throws \Box\Spout\Reader\Exception\SharedStringNotFoundException If a shared string was not found
* @throws \Box\Spout\Common\Exception\IOException If unable to read the sheet data XML * @throws \Box\Spout\Common\Exception\IOException If unable to read the sheet data XML
* @return void
*/ */
protected function readDataForNextRow() protected function readDataForNextRow()
{ {
@ -275,7 +275,8 @@ class RowIterator implements IteratorInterface
protected function getNumRowsRepeatedForCurrentNode($xmlReader) protected function getNumRowsRepeatedForCurrentNode($xmlReader)
{ {
$numRowsRepeated = $xmlReader->getAttribute(self::XML_ATTRIBUTE_NUM_ROWS_REPEATED); $numRowsRepeated = $xmlReader->getAttribute(self::XML_ATTRIBUTE_NUM_ROWS_REPEATED);
return ($numRowsRepeated !== null) ? intval($numRowsRepeated) : 1;
return ($numRowsRepeated !== null) ? (int) $numRowsRepeated : 1;
} }
/** /**
@ -285,7 +286,8 @@ class RowIterator implements IteratorInterface
protected function getNumColumnsRepeatedForCurrentNode($xmlReader) protected function getNumColumnsRepeatedForCurrentNode($xmlReader)
{ {
$numColumnsRepeated = $xmlReader->getAttribute(self::XML_ATTRIBUTE_NUM_COLUMNS_REPEATED); $numColumnsRepeated = $xmlReader->getAttribute(self::XML_ATTRIBUTE_NUM_COLUMNS_REPEATED);
return ($numColumnsRepeated !== null) ? intval($numColumnsRepeated) : 1;
return ($numColumnsRepeated !== null) ? (int) $numColumnsRepeated : 1;
} }
/** /**
@ -306,7 +308,7 @@ class RowIterator implements IteratorInterface
* row data yet (as we still need to apply the "num-columns-repeated" attribute). * row data yet (as we still need to apply the "num-columns-repeated" attribute).
* *
* @param array $rowData * @param array $rowData
* @param string|int|float|bool|\DateTime|\DateInterval|null The value of the last read cell * @param string|int|float|bool|\DateTime|\DateInterval|null $lastReadCellValue The value of the last read cell
* @return bool Whether the row is empty * @return bool Whether the row is empty
*/ */
protected function isEmptyRow($rowData, $lastReadCellValue) protected function isEmptyRow($rowData, $lastReadCellValue)
@ -319,7 +321,7 @@ class RowIterator implements IteratorInterface
/** /**
* Return the current element, from the buffer. * Return the current element, from the buffer.
* @link http://php.net/manual/en/iterator.current.php * @see http://php.net/manual/en/iterator.current.php
* *
* @return array|null * @return array|null
*/ */
@ -330,7 +332,7 @@ class RowIterator implements IteratorInterface
/** /**
* Return the key of the current element * Return the key of the current element
* @link http://php.net/manual/en/iterator.key.php * @see http://php.net/manual/en/iterator.key.php
* *
* @return int * @return int
*/ */
@ -339,7 +341,6 @@ class RowIterator implements IteratorInterface
return $this->lastRowIndexProcessed; return $this->lastRowIndexProcessed;
} }
/** /**
* Cleans up what was created to iterate over the object. * Cleans up what was created to iterate over the object.
* *

View File

@ -3,13 +3,10 @@
namespace Box\Spout\Reader\ODS; namespace Box\Spout\Reader\ODS;
use Box\Spout\Reader\SheetInterface; use Box\Spout\Reader\SheetInterface;
use Box\Spout\Reader\Wrapper\XMLReader;
/** /**
* Class Sheet * Class Sheet
* Represents a sheet within a ODS file * Represents a sheet within a ODS file
*
* @package Box\Spout\Reader\ODS
*/ */
class Sheet implements SheetInterface class Sheet implements SheetInterface
{ {
@ -29,15 +26,14 @@ class Sheet implements SheetInterface
protected $isActive; protected $isActive;
/** /**
* @param XMLReader $xmlReader XML Reader, positioned on the "<table:table>" element * @param RowIterator $rowIterator The corresponding row iterator
* @param int $sheetIndex Index of the sheet, based on order in the workbook (zero-based) * @param int $sheetIndex Index of the sheet, based on order in the workbook (zero-based)
* @param string $sheetName Name of the sheet * @param string $sheetName Name of the sheet
* @param bool $isSheetActive Whether the sheet was defined as active * @param bool $isSheetActive Whether the sheet was defined as active
* @param \Box\Spout\Reader\ODS\ReaderOptions $options Reader's current options
*/ */
public function __construct($xmlReader, $sheetIndex, $sheetName, $isSheetActive, $options) public function __construct($rowIterator, $sheetIndex, $sheetName, $isSheetActive)
{ {
$this->rowIterator = new RowIterator($xmlReader, $options); $this->rowIterator = $rowIterator;
$this->index = $sheetIndex; $this->index = $sheetIndex;
$this->name = $sheetName; $this->name = $sheetName;
$this->isActive = $isSheetActive; $this->isActive = $isSheetActive;

View File

@ -5,14 +5,13 @@ namespace Box\Spout\Reader\ODS;
use Box\Spout\Common\Exception\IOException; use Box\Spout\Common\Exception\IOException;
use Box\Spout\Reader\Exception\XMLProcessingException; use Box\Spout\Reader\Exception\XMLProcessingException;
use Box\Spout\Reader\IteratorInterface; use Box\Spout\Reader\IteratorInterface;
use Box\Spout\Reader\ODS\Creator\EntityFactory;
use Box\Spout\Reader\ODS\Helper\SettingsHelper; use Box\Spout\Reader\ODS\Helper\SettingsHelper;
use Box\Spout\Reader\Wrapper\XMLReader; use Box\Spout\Reader\Wrapper\XMLReader;
/** /**
* Class SheetIterator * Class SheetIterator
* Iterate over ODS sheet. * Iterate over ODS sheet.
*
* @package Box\Spout\Reader\ODS
*/ */
class SheetIterator implements IteratorInterface class SheetIterator implements IteratorInterface
{ {
@ -25,13 +24,16 @@ class SheetIterator implements IteratorInterface
/** @var string $filePath Path of the file to be read */ /** @var string $filePath Path of the file to be read */
protected $filePath; protected $filePath;
/** @var \Box\Spout\Reader\ODS\ReaderOptions Reader's current options */ /** @var \Box\Spout\Common\Manager\OptionsManagerInterface Reader's options manager */
protected $options; protected $optionsManager;
/** @var EntityFactory $entityFactory Factory to create entities */
protected $entityFactory;
/** @var XMLReader The XMLReader object that will help read sheet's XML data */ /** @var XMLReader The XMLReader object that will help read sheet's XML data */
protected $xmlReader; protected $xmlReader;
/** @var \Box\Spout\Common\Escaper\ODS Used to unescape XML data */ /** @var \Box\Spout\Common\Helper\Escaper\ODS Used to unescape XML data */
protected $escaper; protected $escaper;
/** @var bool Whether there are still at least a sheet to be read */ /** @var bool Whether there are still at least a sheet to be read */
@ -45,28 +47,27 @@ class SheetIterator implements IteratorInterface
/** /**
* @param string $filePath Path of the file to be read * @param string $filePath Path of the file to be read
* @param \Box\Spout\Reader\ODS\ReaderOptions $options Reader's current options * @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager
* @throws \Box\Spout\Reader\Exception\NoSheetsFoundException If there are no sheets in the file * @param \Box\Spout\Common\Helper\Escaper\ODS $escaper Used to unescape XML data
* @param SettingsHelper $settingsHelper Helper to get data from "settings.xml"
* @param EntityFactory $entityFactory Factory to create entities
*/ */
public function __construct($filePath, $options) public function __construct($filePath, $optionsManager, $escaper, $settingsHelper, $entityFactory)
{ {
$this->filePath = $filePath; $this->filePath = $filePath;
$this->options = $options; $this->optionsManager = $optionsManager;
$this->xmlReader = new XMLReader(); $this->entityFactory = $entityFactory;
$this->xmlReader = $entityFactory->createXMLReader();
/** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */ $this->escaper = $escaper;
$this->escaper = \Box\Spout\Common\Escaper\ODS::getInstance();
$settingsHelper = new SettingsHelper();
$this->activeSheetName = $settingsHelper->getActiveSheetName($filePath); $this->activeSheetName = $settingsHelper->getActiveSheetName($filePath);
} }
/** /**
* Rewind the Iterator to the first element * Rewind the Iterator to the first element
* @link http://php.net/manual/en/iterator.rewind.php * @see http://php.net/manual/en/iterator.rewind.php
* *
* @return void
* @throws \Box\Spout\Common\Exception\IOException If unable to open the XML file containing sheets' data * @throws \Box\Spout\Common\Exception\IOException If unable to open the XML file containing sheets' data
* @return void
*/ */
public function rewind() public function rewind()
{ {
@ -88,7 +89,7 @@ class SheetIterator implements IteratorInterface
/** /**
* Checks if current position is valid * Checks if current position is valid
* @link http://php.net/manual/en/iterator.valid.php * @see http://php.net/manual/en/iterator.valid.php
* *
* @return bool * @return bool
*/ */
@ -99,7 +100,7 @@ class SheetIterator implements IteratorInterface
/** /**
* Move forward to next element * Move forward to next element
* @link http://php.net/manual/en/iterator.next.php * @see http://php.net/manual/en/iterator.next.php
* *
* @return void * @return void
*/ */
@ -114,7 +115,7 @@ class SheetIterator implements IteratorInterface
/** /**
* Return the current element * Return the current element
* @link http://php.net/manual/en/iterator.current.php * @see http://php.net/manual/en/iterator.current.php
* *
* @return \Box\Spout\Reader\ODS\Sheet * @return \Box\Spout\Reader\ODS\Sheet
*/ */
@ -124,7 +125,7 @@ class SheetIterator implements IteratorInterface
$sheetName = $this->escaper->unescape($escapedSheetName); $sheetName = $this->escaper->unescape($escapedSheetName);
$isActiveSheet = $this->isActiveSheet($sheetName, $this->currentSheetIndex, $this->activeSheetName); $isActiveSheet = $this->isActiveSheet($sheetName, $this->currentSheetIndex, $this->activeSheetName);
return new Sheet($this->xmlReader, $this->currentSheetIndex, $sheetName, $isActiveSheet, $this->options); return $this->entityFactory->createSheet($this->xmlReader, $this->currentSheetIndex, $sheetName, $isActiveSheet, $this->optionsManager);
} }
/** /**
@ -132,7 +133,7 @@ class SheetIterator implements IteratorInterface
* *
* @param string $sheetName Name of the current sheet * @param string $sheetName Name of the current sheet
* @param int $sheetIndex Index of the current sheet * @param int $sheetIndex Index of the current sheet
* @param string|null Name of the sheet that was defined as active or NULL if none defined * @param string|null $activeSheetName Name of the sheet that was defined as active or NULL if none defined
* @return bool Whether the current sheet was defined as the active one * @return bool Whether the current sheet was defined as the active one
*/ */
private function isActiveSheet($sheetName, $sheetIndex, $activeSheetName) private function isActiveSheet($sheetName, $sheetIndex, $activeSheetName)
@ -147,7 +148,7 @@ class SheetIterator implements IteratorInterface
/** /**
* Return the key of the current element * Return the key of the current element
* @link http://php.net/manual/en/iterator.key.php * @see http://php.net/manual/en/iterator.key.php
* *
* @return int * @return int
*/ */

View File

@ -3,31 +3,30 @@
namespace Box\Spout\Reader; namespace Box\Spout\Reader;
use Box\Spout\Common\Exception\IOException; use Box\Spout\Common\Exception\IOException;
use Box\Spout\Common\Helper\GlobalFunctionsHelper;
use Box\Spout\Common\Manager\OptionsManagerInterface;
use Box\Spout\Reader\Common\Creator\EntityFactoryInterface;
use Box\Spout\Reader\Common\Entity\Options;
use Box\Spout\Reader\Exception\ReaderNotOpenedException; use Box\Spout\Reader\Exception\ReaderNotOpenedException;
/** /**
* Class AbstractReader * Class ReaderAbstract
* *
* @package Box\Spout\Reader
* @abstract * @abstract
*/ */
abstract class AbstractReader implements ReaderInterface abstract class ReaderAbstract implements ReaderInterface
{ {
/** @var bool Indicates whether the stream is currently open */ /** @var bool Indicates whether the stream is currently open */
protected $isStreamOpened = false; protected $isStreamOpened = false;
/** @var EntityFactoryInterface Factory to create entities */
protected $entityFactory;
/** @var \Box\Spout\Common\Helper\GlobalFunctionsHelper Helper to work with global functions */ /** @var \Box\Spout\Common\Helper\GlobalFunctionsHelper Helper to work with global functions */
protected $globalFunctionsHelper; protected $globalFunctionsHelper;
/** @var \Box\Spout\Reader\Common\ReaderOptions Reader's customized options */ /** @var OptionsManagerInterface Writer options manager */
protected $options; protected $optionsManager;
/**
* Returns the reader's current options
*
* @return \Box\Spout\Reader\Common\ReaderOptions
*/
abstract protected function getOptions();
/** /**
* Returns whether stream wrappers are supported * Returns whether stream wrappers are supported
@ -47,25 +46,30 @@ abstract class AbstractReader implements ReaderInterface
/** /**
* Returns an iterator to iterate over sheets. * Returns an iterator to iterate over sheets.
* *
* @return \Iterator To iterate over sheets * @return IteratorInterface To iterate over sheets
*/ */
abstract protected function getConcreteSheetIterator(); abstract protected function getConcreteSheetIterator();
/** /**
* Closes the reader. To be used after reading the file. * Closes the reader. To be used after reading the file.
* *
* @return AbstractReader * @return ReaderAbstract
*/ */
abstract protected function closeReader(); abstract protected function closeReader();
/** /**
* @param \Box\Spout\Common\Helper\GlobalFunctionsHelper $globalFunctionsHelper * @param OptionsManagerInterface $optionsManager
* @return AbstractReader * @param GlobalFunctionsHelper $globalFunctionsHelper
* @param EntityFactoryInterface $entityFactory
*/ */
public function setGlobalFunctionsHelper($globalFunctionsHelper) public function __construct(
{ OptionsManagerInterface $optionsManager,
GlobalFunctionsHelper $globalFunctionsHelper,
EntityFactoryInterface $entityFactory
) {
$this->optionsManager = $optionsManager;
$this->globalFunctionsHelper = $globalFunctionsHelper; $this->globalFunctionsHelper = $globalFunctionsHelper;
return $this; $this->entityFactory = $entityFactory;
} }
/** /**
@ -73,11 +77,12 @@ abstract class AbstractReader implements ReaderInterface
* *
* @api * @api
* @param bool $shouldFormatDates * @param bool $shouldFormatDates
* @return AbstractReader * @return ReaderAbstract
*/ */
public function setShouldFormatDates($shouldFormatDates) public function setShouldFormatDates($shouldFormatDates)
{ {
$this->getOptions()->setShouldFormatDates($shouldFormatDates); $this->optionsManager->setOption(Options::SHOULD_FORMAT_DATES, $shouldFormatDates);
return $this; return $this;
} }
@ -86,11 +91,12 @@ abstract class AbstractReader implements ReaderInterface
* *
* @api * @api
* @param bool $shouldPreserveEmptyRows * @param bool $shouldPreserveEmptyRows
* @return AbstractReader * @return ReaderAbstract
*/ */
public function setShouldPreserveEmptyRows($shouldPreserveEmptyRows) public function setShouldPreserveEmptyRows($shouldPreserveEmptyRows)
{ {
$this->getOptions()->setShouldPreserveEmptyRows($shouldPreserveEmptyRows); $this->optionsManager->setOption(Options::SHOULD_PRESERVE_EMPTY_ROWS, $shouldPreserveEmptyRows);
return $this; return $this;
} }
@ -100,8 +106,8 @@ abstract class AbstractReader implements ReaderInterface
* *
* @api * @api
* @param string $filePath Path of the file to be read * @param string $filePath Path of the file to be read
* @return void
* @throws \Box\Spout\Common\Exception\IOException If the file at the given path does not exist, is not readable or is corrupted * @throws \Box\Spout\Common\Exception\IOException If the file at the given path does not exist, is not readable or is corrupted
* @return void
*/ */
public function open($filePath) public function open($filePath)
{ {
@ -113,7 +119,8 @@ abstract class AbstractReader implements ReaderInterface
// we skip the checks if the provided file path points to a PHP stream // we skip the checks if the provided file path points to a PHP stream
if (!$this->globalFunctionsHelper->file_exists($filePath)) { if (!$this->globalFunctionsHelper->file_exists($filePath)) {
throw new IOException("Could not open $filePath for reading! File does not exist."); throw new IOException("Could not open $filePath for reading! File does not exist.");
} else if (!$this->globalFunctionsHelper->is_readable($filePath)) { }
if (!$this->globalFunctionsHelper->is_readable($filePath)) {
throw new IOException("Could not open $filePath for reading! File is not readable."); throw new IOException("Could not open $filePath for reading! File is not readable.");
} }
} }
@ -157,6 +164,7 @@ abstract class AbstractReader implements ReaderInterface
if (preg_match('/^(\w+):\/\//', $filePath, $matches)) { if (preg_match('/^(\w+):\/\//', $filePath, $matches)) {
$streamScheme = $matches[1]; $streamScheme = $matches[1];
} }
return $streamScheme; return $streamScheme;
} }
@ -183,6 +191,7 @@ abstract class AbstractReader implements ReaderInterface
protected function isSupportedStreamWrapper($filePath) protected function isSupportedStreamWrapper($filePath)
{ {
$streamScheme = $this->getStreamWrapperScheme($filePath); $streamScheme = $this->getStreamWrapperScheme($filePath);
return ($streamScheme !== null) ? return ($streamScheme !== null) ?
in_array($streamScheme, $this->globalFunctionsHelper->stream_get_wrappers()) : in_array($streamScheme, $this->globalFunctionsHelper->stream_get_wrappers()) :
true; true;
@ -197,6 +206,7 @@ abstract class AbstractReader implements ReaderInterface
protected function isPhpStream($filePath) protected function isPhpStream($filePath)
{ {
$streamScheme = $this->getStreamWrapperScheme($filePath); $streamScheme = $this->getStreamWrapperScheme($filePath);
return ($streamScheme === 'php'); return ($streamScheme === 'php');
} }
@ -204,8 +214,8 @@ abstract class AbstractReader implements ReaderInterface
* Returns an iterator to iterate over sheets. * Returns an iterator to iterate over sheets.
* *
* @api * @api
* @return \Iterator To iterate over sheets
* @throws \Box\Spout\Reader\Exception\ReaderNotOpenedException If called before opening the reader * @throws \Box\Spout\Reader\Exception\ReaderNotOpenedException If called before opening the reader
* @return \Iterator To iterate over sheets
*/ */
public function getSheetIterator() public function getSheetIterator()
{ {

View File

@ -2,16 +2,15 @@
namespace Box\Spout\Reader; namespace Box\Spout\Reader;
use Box\Spout\Common\Creator\HelperFactory;
use Box\Spout\Common\Exception\UnsupportedTypeException; use Box\Spout\Common\Exception\UnsupportedTypeException;
use Box\Spout\Common\Helper\GlobalFunctionsHelper;
use Box\Spout\Common\Type; use Box\Spout\Common\Type;
use Box\Spout\Reader\XLSX\Manager\SharedStringsCaching\CachingStrategyFactory;
/** /**
* Class ReaderFactory * Class ReaderFactory
* This factory is used to create readers, based on the type of the file to be read. * This factory is used to create readers, based on the type of the file to be read.
* It supports CSV and XLSX formats. * It supports CSV and XLSX formats.
*
* @package Box\Spout\Reader
*/ */
class ReaderFactory class ReaderFactory
{ {
@ -20,29 +19,57 @@ class ReaderFactory
* *
* @api * @api
* @param string $readerType Type of the reader to instantiate * @param string $readerType Type of the reader to instantiate
* @return ReaderInterface
* @throws \Box\Spout\Common\Exception\UnsupportedTypeException * @throws \Box\Spout\Common\Exception\UnsupportedTypeException
* @return ReaderInterface
*/ */
public static function create($readerType) public static function create($readerType)
{ {
$reader = null;
switch ($readerType) { switch ($readerType) {
case Type::CSV: case Type::CSV: return self::getCSVReader();
$reader = new CSV\Reader(); case Type::XLSX: return self::getXLSXReader();
break; case Type::ODS: return self::getODSReader();
case Type::XLSX:
$reader = new XLSX\Reader();
break;
case Type::ODS:
$reader = new ODS\Reader();
break;
default: default:
throw new UnsupportedTypeException('No readers supporting the given type: ' . $readerType); throw new UnsupportedTypeException('No readers supporting the given type: ' . $readerType);
} }
}
$reader->setGlobalFunctionsHelper(new GlobalFunctionsHelper()); /**
* @return CSV\Reader
*/
private static function getCSVReader()
{
$optionsManager = new CSV\Manager\OptionsManager();
$helperFactory = new HelperFactory();
$entityFactory = new CSV\Creator\EntityFactory($helperFactory);
$globalFunctionsHelper = $helperFactory->createGlobalFunctionsHelper();
return $reader; return new CSV\Reader($optionsManager, $globalFunctionsHelper, $entityFactory);
}
/**
* @return XLSX\Reader
*/
private static function getXLSXReader()
{
$optionsManager = new XLSX\Manager\OptionsManager();
$helperFactory = new XLSX\Creator\HelperFactory();
$managerFactory = new XLSX\Creator\ManagerFactory($helperFactory, new CachingStrategyFactory());
$entityFactory = new XLSX\Creator\EntityFactory($managerFactory, $helperFactory);
$globalFunctionsHelper = $helperFactory->createGlobalFunctionsHelper();
return new XLSX\Reader($optionsManager, $globalFunctionsHelper, $entityFactory, $managerFactory);
}
/**
* @return ODS\Reader
*/
private static function getODSReader()
{
$optionsManager = new ODS\Manager\OptionsManager();
$helperFactory = new ODS\Creator\HelperFactory();
$entityFactory = new ODS\Creator\EntityFactory($helperFactory);
$globalFunctionsHelper = $helperFactory->createGlobalFunctionsHelper();
return new ODS\Reader($optionsManager, $globalFunctionsHelper, $entityFactory);
} }
} }

View File

@ -4,8 +4,6 @@ namespace Box\Spout\Reader;
/** /**
* Interface ReaderInterface * Interface ReaderInterface
*
* @package Box\Spout\Reader
*/ */
interface ReaderInterface interface ReaderInterface
{ {
@ -14,16 +12,16 @@ interface ReaderInterface
* that the file exists and is readable. * that the file exists and is readable.
* *
* @param string $filePath Path of the file to be read * @param string $filePath Path of the file to be read
* @return void
* @throws \Box\Spout\Common\Exception\IOException * @throws \Box\Spout\Common\Exception\IOException
* @return void
*/ */
public function open($filePath); public function open($filePath);
/** /**
* Returns an iterator to iterate over sheets. * Returns an iterator to iterate over sheets.
* *
* @return \Iterator To iterate over sheets
* @throws \Box\Spout\Reader\Exception\ReaderNotOpenedException If called before opening the reader * @throws \Box\Spout\Reader\Exception\ReaderNotOpenedException If called before opening the reader
* @return \Iterator To iterate over sheets
*/ */
public function getSheetIterator(); public function getSheetIterator();

View File

@ -4,15 +4,13 @@ namespace Box\Spout\Reader;
/** /**
* Interface SheetInterface * Interface SheetInterface
*
* @package Box\Spout\Reader
*/ */
interface SheetInterface interface SheetInterface
{ {
/** /**
* Returns an iterator to iterate over the sheet's rows. * Returns an iterator to iterate over the sheet's rows.
* *
* @return \Iterator * @return IteratorInterface
*/ */
public function getRowIterator(); public function getRowIterator();
} }

View File

@ -6,8 +6,6 @@ use Box\Spout\Reader\Exception\XMLProcessingException;
/** /**
* Trait XMLInternalErrorsHelper * Trait XMLInternalErrorsHelper
*
* @package Box\Spout\Reader\Wrapper
*/ */
trait XMLInternalErrorsHelper trait XMLInternalErrorsHelper
{ {
@ -30,8 +28,8 @@ trait XMLInternalErrorsHelper
* Throws an XMLProcessingException if an error occured. * Throws an XMLProcessingException if an error occured.
* It also always resets the "libxml_use_internal_errors" setting back to its initial value. * It also always resets the "libxml_use_internal_errors" setting back to its initial value.
* *
* @return void
* @throws \Box\Spout\Reader\Exception\XMLProcessingException * @throws \Box\Spout\Reader\Exception\XMLProcessingException
* @return void
*/ */
protected function resetXMLInternalErrorsSettingAndThrowIfXMLErrorOccured() protected function resetXMLInternalErrorsSettingAndThrowIfXMLErrorOccured()
{ {
@ -57,7 +55,7 @@ trait XMLInternalErrorsHelper
* Returns the error message for the last XML error that occured. * Returns the error message for the last XML error that occured.
* @see libxml_get_last_error * @see libxml_get_last_error
* *
* @return String|null Last XML error message or null if no error * @return string|null Last XML error message or null if no error
*/ */
private function getLastXMLErrorMessage() private function getLastXMLErrorMessage()
{ {
@ -78,5 +76,4 @@ trait XMLInternalErrorsHelper
{ {
libxml_use_internal_errors($this->initialUseInternalErrorsValue); libxml_use_internal_errors($this->initialUseInternalErrorsValue);
} }
} }

View File

@ -1,15 +1,11 @@
<?php <?php
namespace Box\Spout\Reader\Wrapper; namespace Box\Spout\Reader\Wrapper;
use DOMNode;
/** /**
* Class XMLReader * Class XMLReader
* Wrapper around the built-in XMLReader * Wrapper around the built-in XMLReader
* @see \XMLReader * @see \XMLReader
*
* @package Box\Spout\Reader\Wrapper
*/ */
class XMLReader extends \XMLReader class XMLReader extends \XMLReader
{ {
@ -81,8 +77,8 @@ class XMLReader extends \XMLReader
* Move to next node in document * Move to next node in document
* @see \XMLReader::read * @see \XMLReader::read
* *
* @return bool TRUE on success or FALSE on failure
* @throws \Box\Spout\Reader\Exception\XMLProcessingException If an error/warning occurred * @throws \Box\Spout\Reader\Exception\XMLProcessingException If an error/warning occurred
* @return bool TRUE on success or FALSE on failure
*/ */
public function read() public function read()
{ {
@ -99,8 +95,8 @@ class XMLReader extends \XMLReader
* Read until the element with the given name is found, or the end of the file. * Read until the element with the given name is found, or the end of the file.
* *
* @param string $nodeName Name of the node to find * @param string $nodeName Name of the node to find
* @return bool TRUE on success or FALSE on failure
* @throws \Box\Spout\Reader\Exception\XMLProcessingException If an error/warning occurred * @throws \Box\Spout\Reader\Exception\XMLProcessingException If an error/warning occurred
* @return bool TRUE on success or FALSE on failure
*/ */
public function readUntilNodeFound($nodeName) public function readUntilNodeFound($nodeName)
{ {
@ -116,9 +112,9 @@ class XMLReader extends \XMLReader
* Move cursor to next node skipping all subtrees * Move cursor to next node skipping all subtrees
* @see \XMLReader::next * @see \XMLReader::next
* *
* @param string|void $localName The name of the next node to move to * @param string|null $localName The name of the next node to move to
* @return bool TRUE on success or FALSE on failure
* @throws \Box\Spout\Reader\Exception\XMLProcessingException If an error/warning occurred * @throws \Box\Spout\Reader\Exception\XMLProcessingException If an error/warning occurred
* @return bool TRUE on success or FALSE on failure
*/ */
public function next($localName = null) public function next($localName = null)
{ {
@ -137,7 +133,7 @@ class XMLReader extends \XMLReader
*/ */
public function isPositionedOnStartingNode($nodeName) public function isPositionedOnStartingNode($nodeName)
{ {
return $this->isPositionedOnNode($nodeName, XMLReader::ELEMENT); return $this->isPositionedOnNode($nodeName, self::ELEMENT);
} }
/** /**
@ -146,7 +142,7 @@ class XMLReader extends \XMLReader
*/ */
public function isPositionedOnEndingNode($nodeName) public function isPositionedOnEndingNode($nodeName)
{ {
return $this->isPositionedOnNode($nodeName, XMLReader::END_ELEMENT); return $this->isPositionedOnNode($nodeName, self::END_ELEMENT);
} }
/** /**

View File

@ -0,0 +1,126 @@
<?php
namespace Box\Spout\Reader\XLSX\Creator;
use Box\Spout\Reader\Common\Creator\EntityFactoryInterface;
use Box\Spout\Reader\Common\Entity\Options;
use Box\Spout\Reader\Common\XMLProcessor;
use Box\Spout\Reader\Wrapper\XMLReader;
use Box\Spout\Reader\XLSX\Manager\SharedStringsManager;
use Box\Spout\Reader\XLSX\RowIterator;
use Box\Spout\Reader\XLSX\Sheet;
use Box\Spout\Reader\XLSX\SheetIterator;
use MongoDB\Driver\Manager;
/**
* Class EntityFactory
* Factory to create entities
*/
class EntityFactory implements EntityFactoryInterface
{
/** @var HelperFactory */
private $helperFactory;
/** @var ManagerFactory */
private $managerFactory;
/**
* @param ManagerFactory $managerFactory
* @param HelperFactory $helperFactory
*/
public function __construct(ManagerFactory $managerFactory, HelperFactory $helperFactory)
{
$this->managerFactory = $managerFactory;
$this->helperFactory = $helperFactory;
}
/**
* @param string $filePath Path of the file to be read
* @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager Reader's options manager
* @param SharedStringsManager $sharedStringsManager Manages shared strings
* @return SheetIterator
*/
public function createSheetIterator($filePath, $optionsManager, $sharedStringsManager)
{
$sheetManager = $this->managerFactory->createSheetManager($filePath, $optionsManager, $sharedStringsManager, $this);
return new SheetIterator($sheetManager);
}
/**
* @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 SharedStringsManager $sharedStringsManager Manages shared strings
* @return Sheet
*/
public function createSheet(
$filePath,
$sheetDataXMLFilePath,
$sheetIndex,
$sheetName,
$isSheetActive,
$optionsManager,
$sharedStringsManager
) {
$rowIterator = $this->createRowIterator($filePath, $sheetDataXMLFilePath, $optionsManager, $sharedStringsManager);
return new Sheet($rowIterator, $sheetIndex, $sheetName, $isSheetActive);
}
/**
* @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 SharedStringsManager $sharedStringsManager Manages shared strings
* @return RowIterator
*/
private function createRowIterator($filePath, $sheetDataXMLFilePath, $optionsManager, $sharedStringsManager)
{
$xmlReader = $this->createXMLReader();
$xmlProcessor = $this->createXMLProcessor($xmlReader);
$styleManager = $this->managerFactory->createStyleManager($filePath, $this);
$shouldFormatDates = $optionsManager->getOption(Options::SHOULD_FORMAT_DATES);
$cellValueFormatter = $this->helperFactory->createCellValueFormatter($sharedStringsManager, $styleManager, $shouldFormatDates);
$shouldPreserveEmptyRows = $optionsManager->getOption(Options::SHOULD_PRESERVE_EMPTY_ROWS);
return new RowIterator(
$filePath,
$sheetDataXMLFilePath,
$shouldPreserveEmptyRows,
$xmlReader,
$xmlProcessor,
$cellValueFormatter
);
}
/**
* @return \ZipArchive
*/
public function createZipArchive()
{
return new \ZipArchive();
}
/**
* @return XMLReader
*/
public function createXMLReader()
{
return new XMLReader();
}
/**
* @param $xmlReader
* @return XMLProcessor
*/
public function createXMLProcessor($xmlReader)
{
return new XMLProcessor($xmlReader);
}
}

View File

@ -0,0 +1,37 @@
<?php
namespace Box\Spout\Reader\XLSX\Creator;
use Box\Spout\Common\Helper\Escaper;
use Box\Spout\Reader\XLSX\Helper\CellValueFormatter;
use Box\Spout\Reader\XLSX\Manager\SharedStringsManager;
use Box\Spout\Reader\XLSX\Manager\StyleManager;
/**
* Class HelperFactory
* Factory to create helpers
*/
class HelperFactory extends \Box\Spout\Common\Creator\HelperFactory
{
/**
* @param SharedStringsManager $sharedStringsManager Manages shared strings
* @param StyleManager $styleManager Manages styles
* @param bool $shouldFormatDates Whether date/time values should be returned as PHP objects or be formatted as strings
* @return CellValueFormatter
*/
public function createCellValueFormatter($sharedStringsManager, $styleManager, $shouldFormatDates)
{
$escaper = $this->createStringsEscaper();
return new CellValueFormatter($sharedStringsManager, $styleManager, $shouldFormatDates, $escaper);
}
/**
* @return Escaper\XLSX
*/
public function createStringsEscaper()
{
/* @noinspection PhpUnnecessaryFullyQualifiedNameInspection */
return new Escaper\XLSX();
}
}

View File

@ -0,0 +1,66 @@
<?php
namespace Box\Spout\Reader\XLSX\Creator;
use Box\Spout\Reader\XLSX\Manager\SharedStringsCaching\CachingStrategyFactory;
use Box\Spout\Reader\XLSX\Manager\SharedStringsManager;
use Box\Spout\Reader\XLSX\Manager\SheetManager;
use Box\Spout\Reader\XLSX\Manager\StyleManager;
/**
* Class ManagerFactory
* Factory to create managers
*/
class ManagerFactory
{
/** @var HelperFactory */
private $helperFactory;
/** @var CachingStrategyFactory */
private $cachingStrategyFactory;
/**
* @param HelperFactory $helperFactory Factory to create helpers
* @param CachingStrategyFactory $cachingStrategyFactory Factory to create shared strings caching strategies
*/
public function __construct(HelperFactory $helperFactory, CachingStrategyFactory $cachingStrategyFactory)
{
$this->helperFactory = $helperFactory;
$this->cachingStrategyFactory = $cachingStrategyFactory;
}
/**
* @param string $filePath Path of the XLSX file being read
* @param string $tempFolder Temporary folder where the temporary files to store shared strings will be stored
* @param EntityFactory $entityFactory Factory to create entities
* @return SharedStringsManager
*/
public function createSharedStringsManager($filePath, $tempFolder, $entityFactory)
{
return new SharedStringsManager($filePath, $tempFolder, $entityFactory, $this->helperFactory, $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\Manager\SharedStringsManager $sharedStringsManager Manages shared strings
* @param EntityFactory $entityFactory Factory to create entities
* @return SheetManager
*/
public function createSheetManager($filePath, $optionsManager, $sharedStringsManager, $entityFactory)
{
$escaper = $this->helperFactory->createStringsEscaper();
return new SheetManager($filePath, $optionsManager, $sharedStringsManager, $escaper, $entityFactory);
}
/**
* @param string $filePath Path of the XLSX file being read
* @param EntityFactory $entityFactory Factory to create entities
* @return StyleManager
*/
public function createStyleManager($filePath, $entityFactory)
{
return new StyleManager($filePath, $entityFactory);
}
}

View File

@ -7,8 +7,6 @@ use Box\Spout\Common\Exception\InvalidArgumentException;
/** /**
* Class CellHelper * Class CellHelper
* This class provides helper functions when working with cells * This class provides helper functions when working with cells
*
* @package Box\Spout\Reader\XLSX\Helper
*/ */
class CellHelper class CellHelper
{ {
@ -26,7 +24,7 @@ class CellHelper
* Calling fillMissingArrayIndexes($dataArray, 'FILL') will return this array: ['FILL', 1, 'FILL', 3] * Calling fillMissingArrayIndexes($dataArray, 'FILL') will return this array: ['FILL', 1, 'FILL', 3]
* *
* @param array $dataArray The array to fill * @param array $dataArray The array to fill
* @param string|void $fillValue optional * @param string $fillValue optional
* @return array * @return array
*/ */
public static function fillMissingArrayIndexes($dataArray, $fillValue = '') public static function fillMissingArrayIndexes($dataArray, $fillValue = '')
@ -51,8 +49,8 @@ class CellHelper
* The mapping is zero based, so that A1 maps to 0, B2 maps to 1, Z13 to 25 and AA4 to 26. * The mapping is zero based, so that A1 maps to 0, B2 maps to 1, Z13 to 25 and AA4 to 26.
* *
* @param string $cellIndex The Excel cell index ('A1', 'BC13', ...) * @param string $cellIndex The Excel cell index ('A1', 'BC13', ...)
* @return int
* @throws \Box\Spout\Common\Exception\InvalidArgumentException When the given cell index is invalid * @throws \Box\Spout\Common\Exception\InvalidArgumentException When the given cell index is invalid
* @return int
*/ */
public static function getColumnIndexFromCellIndex($cellIndex) public static function getColumnIndexFromCellIndex($cellIndex)
{ {

View File

@ -2,11 +2,12 @@
namespace Box\Spout\Reader\XLSX\Helper; namespace Box\Spout\Reader\XLSX\Helper;
use Box\Spout\Reader\XLSX\Manager\SharedStringsManager;
use Box\Spout\Reader\XLSX\Manager\StyleManager;
/** /**
* Class CellValueFormatter * Class CellValueFormatter
* This class provides helper functions to format cell values * This class provides helper functions to format cell values
*
* @package Box\Spout\Reader\XLSX\Helper
*/ */
class CellValueFormatter class CellValueFormatter
{ {
@ -38,31 +39,30 @@ class CellValueFormatter
*/ */
const ERRONEOUS_EXCEL_LEAP_YEAR_DAY = 60; const ERRONEOUS_EXCEL_LEAP_YEAR_DAY = 60;
/** @var SharedStringsHelper Helper to work with shared strings */ /** @var SharedStringsManager Manages shared strings */
protected $sharedStringsHelper; protected $sharedStringsManager;
/** @var StyleHelper Helper to work with styles */ /** @var StyleManager Manages styles */
protected $styleHelper; protected $styleManager;
/** @var bool Whether date/time values should be returned as PHP objects or be formatted as strings */ /** @var bool Whether date/time values should be returned as PHP objects or be formatted as strings */
protected $shouldFormatDates; protected $shouldFormatDates;
/** @var \Box\Spout\Common\Escaper\XLSX Used to unescape XML data */ /** @var \Box\Spout\Common\Helper\Escaper\XLSX Used to unescape XML data */
protected $escaper; protected $escaper;
/** /**
* @param SharedStringsHelper $sharedStringsHelper Helper to work with shared strings * @param SharedStringsManager $sharedStringsManager Manages shared strings
* @param StyleHelper $styleHelper Helper to work with styles * @param StyleManager $styleManager Manages styles
* @param bool $shouldFormatDates Whether date/time values should be returned as PHP objects or be formatted as strings * @param bool $shouldFormatDates Whether date/time values should be returned as PHP objects or be formatted as strings
* @param \Box\Spout\Common\Helper\Escaper\XLSX $escaper Used to unescape XML data
*/ */
public function __construct($sharedStringsHelper, $styleHelper, $shouldFormatDates) public function __construct($sharedStringsManager, $styleManager, $shouldFormatDates, $escaper)
{ {
$this->sharedStringsHelper = $sharedStringsHelper; $this->sharedStringsManager = $sharedStringsManager;
$this->styleHelper = $styleHelper; $this->styleManager = $styleManager;
$this->shouldFormatDates = $shouldFormatDates; $this->shouldFormatDates = $shouldFormatDates;
$this->escaper = $escaper;
/** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */
$this->escaper = \Box\Spout\Common\Escaper\XLSX::getInstance();
} }
/** /**
@ -75,7 +75,7 @@ class CellValueFormatter
{ {
// Default cell type is "n" // Default cell type is "n"
$cellType = $node->getAttribute(self::XML_ATTRIBUTE_TYPE) ?: self::CELL_TYPE_NUMERIC; $cellType = $node->getAttribute(self::XML_ATTRIBUTE_TYPE) ?: self::CELL_TYPE_NUMERIC;
$cellStyleId = intval($node->getAttribute(self::XML_ATTRIBUTE_STYLE_ID)); $cellStyleId = (int) $node->getAttribute(self::XML_ATTRIBUTE_STYLE_ID);
$vNodeValue = $this->getVNodeValue($node); $vNodeValue = $this->getVNodeValue($node);
if (($vNodeValue === '') && ($cellType !== self::CELL_TYPE_INLINE_STRING)) { if (($vNodeValue === '') && ($cellType !== self::CELL_TYPE_INLINE_STRING)) {
@ -111,6 +111,7 @@ class CellValueFormatter
// for cell types having a "v" tag containing the value. // for cell types having a "v" tag containing the value.
// if not, the returned value should be empty string. // if not, the returned value should be empty string.
$vNode = $node->getElementsByTagName(self::XML_NODE_VALUE)->item(0); $vNode = $node->getElementsByTagName(self::XML_NODE_VALUE)->item(0);
return ($vNode !== null) ? $vNode->nodeValue : ''; return ($vNode !== null) ? $vNode->nodeValue : '';
} }
@ -126,6 +127,7 @@ class CellValueFormatter
// <c r="A1" t="inlineStr"><is><t>[INLINE_STRING]</t></is></c> // <c r="A1" t="inlineStr"><is><t>[INLINE_STRING]</t></is></c>
$tNode = $node->getElementsByTagName(self::XML_NODE_INLINE_STRING_VALUE)->item(0); $tNode = $node->getElementsByTagName(self::XML_NODE_INLINE_STRING_VALUE)->item(0);
$cellValue = $this->escaper->unescape($tNode->nodeValue); $cellValue = $this->escaper->unescape($tNode->nodeValue);
return $cellValue; return $cellValue;
} }
@ -139,9 +141,10 @@ class CellValueFormatter
{ {
// shared strings are formatted this way: // shared strings are formatted this way:
// <c r="A1" t="s"><v>[SHARED_STRING_INDEX]</v></c> // <c r="A1" t="s"><v>[SHARED_STRING_INDEX]</v></c>
$sharedStringIndex = intval($nodeValue); $sharedStringIndex = (int) $nodeValue;
$escapedCellValue = $this->sharedStringsHelper->getStringAtIndex($sharedStringIndex); $escapedCellValue = $this->sharedStringsManager->getStringAtIndex($sharedStringIndex);
$cellValue = $this->escaper->unescape($escapedCellValue); $cellValue = $this->escaper->unescape($escapedCellValue);
return $cellValue; return $cellValue;
} }
@ -155,6 +158,7 @@ class CellValueFormatter
{ {
$escapedCellValue = trim($nodeValue); $escapedCellValue = trim($nodeValue);
$cellValue = $this->escaper->unescape($escapedCellValue); $cellValue = $this->escaper->unescape($escapedCellValue);
return $cellValue; return $cellValue;
} }
@ -170,14 +174,17 @@ class CellValueFormatter
{ {
// Numeric values can represent numbers as well as timestamps. // Numeric values can represent numbers as well as timestamps.
// We need to look at the style of the cell to determine whether it is one or the other. // We need to look at the style of the cell to determine whether it is one or the other.
$shouldFormatAsDate = $this->styleHelper->shouldFormatNumericValueAsDate($cellStyleId); $shouldFormatAsDate = $this->styleManager->shouldFormatNumericValueAsDate($cellStyleId);
if ($shouldFormatAsDate) { if ($shouldFormatAsDate) {
return $this->formatExcelTimestampValue(floatval($nodeValue), $cellStyleId); $cellValue = $this->formatExcelTimestampValue((float) $nodeValue, $cellStyleId);
} else { } else {
$nodeIntValue = intval($nodeValue); $nodeIntValue = (int) $nodeValue;
return ($nodeIntValue == $nodeValue) ? $nodeIntValue : floatval($nodeValue); $nodeFloatValue = (float) $nodeValue;
$cellValue = ((float) $nodeIntValue === $nodeFloatValue) ? $nodeIntValue : $nodeFloatValue;
} }
return $cellValue;
} }
/** /**
@ -198,14 +205,16 @@ class CellValueFormatter
if ($nodeValue >= 1) { if ($nodeValue >= 1) {
// Values greater than 1 represent "dates". The value 1.0 representing the "base" date: 1900-01-01. // Values greater than 1 represent "dates". The value 1.0 representing the "base" date: 1900-01-01.
return $this->formatExcelTimestampValueAsDateValue($nodeValue, $cellStyleId); $cellValue = $this->formatExcelTimestampValueAsDateValue($nodeValue, $cellStyleId);
} elseif ($nodeValue >= 0) { } elseif ($nodeValue >= 0) {
// Values between 0 and 1 represent "times". // Values between 0 and 1 represent "times".
return $this->formatExcelTimestampValueAsTimeValue($nodeValue, $cellStyleId); $cellValue = $this->formatExcelTimestampValueAsTimeValue($nodeValue, $cellStyleId);
} else { } else {
// invalid date // invalid date
return null; $cellValue = null;
} }
return $cellValue;
} }
/** /**
@ -228,12 +237,14 @@ class CellValueFormatter
$dateObj->setTime($hours, $minutes, $seconds); $dateObj->setTime($hours, $minutes, $seconds);
if ($this->shouldFormatDates) { if ($this->shouldFormatDates) {
$styleNumberFormatCode = $this->styleHelper->getNumberFormatCode($cellStyleId); $styleNumberFormatCode = $this->styleManager->getNumberFormatCode($cellStyleId);
$phpDateFormat = DateFormatHelper::toPHPDateFormat($styleNumberFormatCode); $phpDateFormat = DateFormatHelper::toPHPDateFormat($styleNumberFormatCode);
return $dateObj->format($phpDateFormat); $cellValue = $dateObj->format($phpDateFormat);
} else { } else {
return $dateObj; $cellValue = $dateObj;
} }
return $cellValue;
} }
/** /**
@ -253,19 +264,21 @@ class CellValueFormatter
try { try {
$dateObj = \DateTime::createFromFormat('|Y-m-d', '1899-12-31'); $dateObj = \DateTime::createFromFormat('|Y-m-d', '1899-12-31');
$dateObj->modify('+' . intval($nodeValue) . 'days'); $dateObj->modify('+' . (int) $nodeValue . 'days');
$dateObj->modify('+' . $secondsRemainder . 'seconds'); $dateObj->modify('+' . $secondsRemainder . 'seconds');
if ($this->shouldFormatDates) { if ($this->shouldFormatDates) {
$styleNumberFormatCode = $this->styleHelper->getNumberFormatCode($cellStyleId); $styleNumberFormatCode = $this->styleManager->getNumberFormatCode($cellStyleId);
$phpDateFormat = DateFormatHelper::toPHPDateFormat($styleNumberFormatCode); $phpDateFormat = DateFormatHelper::toPHPDateFormat($styleNumberFormatCode);
return $dateObj->format($phpDateFormat); $cellValue = $dateObj->format($phpDateFormat);
} else { } else {
return $dateObj; $cellValue = $dateObj;
} }
} catch (\Exception $e) { } catch (\Exception $e) {
return null; $cellValue = null;
} }
return $cellValue;
} }
/** /**
@ -276,9 +289,7 @@ class CellValueFormatter
*/ */
protected function formatBooleanCellValue($nodeValue) protected function formatBooleanCellValue($nodeValue)
{ {
// !! is similar to boolval() return (bool) $nodeValue;
$cellValue = !!$nodeValue;
return $cellValue;
} }
/** /**
@ -292,9 +303,11 @@ class CellValueFormatter
{ {
// Mitigate thrown Exception on invalid date-time format (http://php.net/manual/en/datetime.construct.php) // Mitigate thrown Exception on invalid date-time format (http://php.net/manual/en/datetime.construct.php)
try { try {
return ($this->shouldFormatDates) ? $nodeValue : new \DateTime($nodeValue); $cellValue = ($this->shouldFormatDates) ? $nodeValue : new \DateTime($nodeValue);
} catch (\Exception $e) { } catch (\Exception $e) {
return null; $cellValue = null;
} }
return $cellValue;
} }
} }

View File

@ -5,8 +5,6 @@ namespace Box\Spout\Reader\XLSX\Helper;
/** /**
* Class DateFormatHelper * Class DateFormatHelper
* This class provides helper functions to format Excel dates * This class provides helper functions to format Excel dates
*
* @package Box\Spout\Reader\XLSX\Helper
*/ */
class DateFormatHelper class DateFormatHelper
{ {
@ -107,6 +105,7 @@ class DateFormatHelper
$phpDateFormat = preg_replace_callback('/"(.+?)"/', function ($matches) { $phpDateFormat = preg_replace_callback('/"(.+?)"/', function ($matches) {
$stringToEscape = $matches[1]; $stringToEscape = $matches[1];
$letters = preg_split('//u', $stringToEscape, -1, PREG_SPLIT_NO_EMPTY); $letters = preg_split('//u', $stringToEscape, -1, PREG_SPLIT_NO_EMPTY);
return '\\' . implode('\\', $letters); return '\\' . implode('\\', $letters);
}, $phpDateFormat); }, $phpDateFormat);

View File

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

View File

@ -1,11 +1,11 @@
<?php <?php
namespace Box\Spout\Reader\XLSX\Helper\SharedStringsCaching; namespace Box\Spout\Reader\XLSX\Manager\SharedStringsCaching;
use Box\Spout\Reader\XLSX\Creator\HelperFactory;
/** /**
* Class CachingStrategyFactory * Class CachingStrategyFactory
*
* @package Box\Spout\Reader\XLSX\Helper\SharedStringsCaching
*/ */
class CachingStrategyFactory class CachingStrategyFactory
{ {
@ -50,44 +50,21 @@ class CachingStrategyFactory
*/ */
const MAX_NUM_STRINGS_PER_TEMP_FILE = 10000; const MAX_NUM_STRINGS_PER_TEMP_FILE = 10000;
/** @var CachingStrategyFactory|null Singleton instance */
protected static $instance = null;
/**
* Private constructor for singleton
*/
private function __construct()
{
}
/**
* Returns the singleton instance of the factory
*
* @return CachingStrategyFactory
*/
public static function getInstance()
{
if (self::$instance === null) {
self::$instance = new CachingStrategyFactory();
}
return self::$instance;
}
/** /**
* Returns the best caching strategy, given the number of unique shared strings * Returns the best caching strategy, given the number of unique shared strings
* and the amount of memory available. * and the amount of memory available.
* *
* @param int|null $sharedStringsUniqueCount Number of unique shared strings (NULL if unknown) * @param int|null $sharedStringsUniqueCount Number of unique shared strings (NULL if unknown)
* @param string|void $tempFolder Temporary folder where the temporary files to store shared strings will be stored * @param string $tempFolder Temporary folder where the temporary files to store shared strings will be stored
* @param HelperFactory $helperFactory Factory to create helpers
* @return CachingStrategyInterface The best caching strategy * @return CachingStrategyInterface The best caching strategy
*/ */
public function getBestCachingStrategy($sharedStringsUniqueCount, $tempFolder = null) public function createBestCachingStrategy($sharedStringsUniqueCount, $tempFolder, $helperFactory)
{ {
if ($this->isInMemoryStrategyUsageSafe($sharedStringsUniqueCount)) { if ($this->isInMemoryStrategyUsageSafe($sharedStringsUniqueCount)) {
return new InMemoryStrategy($sharedStringsUniqueCount); return new InMemoryStrategy($sharedStringsUniqueCount);
} else { } else {
return new FileBasedStrategy($tempFolder, self::MAX_NUM_STRINGS_PER_TEMP_FILE); return new FileBasedStrategy($tempFolder, self::MAX_NUM_STRINGS_PER_TEMP_FILE, $helperFactory);
} }
} }
@ -109,11 +86,13 @@ class CachingStrategyFactory
if ($memoryAvailable === -1) { if ($memoryAvailable === -1) {
// if cannot get memory limit or if memory limit set as unlimited, don't trust and play safe // if cannot get memory limit or if memory limit set as unlimited, don't trust and play safe
return ($sharedStringsUniqueCount < self::MAX_NUM_STRINGS_PER_TEMP_FILE); $isInMemoryStrategyUsageSafe = ($sharedStringsUniqueCount < self::MAX_NUM_STRINGS_PER_TEMP_FILE);
} else { } else {
$memoryNeeded = $sharedStringsUniqueCount * self::AMOUNT_MEMORY_NEEDED_PER_STRING_IN_KB; $memoryNeeded = $sharedStringsUniqueCount * self::AMOUNT_MEMORY_NEEDED_PER_STRING_IN_KB;
return ($memoryAvailable > $memoryNeeded); $isInMemoryStrategyUsageSafe = ($memoryAvailable > $memoryNeeded);
} }
return $isInMemoryStrategyUsageSafe;
} }
/** /**
@ -132,7 +111,7 @@ class CachingStrategyFactory
} }
if (preg_match('/(\d+)([bkmgt])b?/', $memoryLimitFormatted, $matches)) { if (preg_match('/(\d+)([bkmgt])b?/', $memoryLimitFormatted, $matches)) {
$amount = intval($matches[1]); $amount = (int) ($matches[1]);
$unit = $matches[2]; $unit = $matches[2];
switch ($unit) { switch ($unit) {

View File

@ -1,11 +1,9 @@
<?php <?php
namespace Box\Spout\Reader\XLSX\Helper\SharedStringsCaching; namespace Box\Spout\Reader\XLSX\Manager\SharedStringsCaching;
/** /**
* Interface CachingStrategyInterface * Interface CachingStrategyInterface
*
* @package Box\Spout\Reader\XLSX\Helper\SharedStringsCaching
*/ */
interface CachingStrategyInterface interface CachingStrategyInterface
{ {
@ -30,8 +28,8 @@ interface CachingStrategyInterface
* Returns the string located at the given index from the cache. * Returns the string located at the given index from the cache.
* *
* @param int $sharedStringIndex Index of the shared string in the sharedStrings.xml file * @param int $sharedStringIndex Index of the shared string in the sharedStrings.xml file
* @return string The shared string at the given index
* @throws \Box\Spout\Reader\Exception\SharedStringNotFoundException If no shared string found for the given index * @throws \Box\Spout\Reader\Exception\SharedStringNotFoundException If no shared string found for the given index
* @return string The shared string at the given index
*/ */
public function getStringAtIndex($sharedStringIndex); public function getStringAtIndex($sharedStringIndex);

View File

@ -1,10 +1,9 @@
<?php <?php
namespace Box\Spout\Reader\XLSX\Helper\SharedStringsCaching; namespace Box\Spout\Reader\XLSX\Manager\SharedStringsCaching;
use Box\Spout\Common\Helper\FileSystemHelper;
use Box\Spout\Common\Helper\GlobalFunctionsHelper;
use Box\Spout\Reader\Exception\SharedStringNotFoundException; use Box\Spout\Reader\Exception\SharedStringNotFoundException;
use Box\Spout\Reader\XLSX\Creator\HelperFactory;
/** /**
* Class FileBasedStrategy * Class FileBasedStrategy
@ -12,8 +11,6 @@ use Box\Spout\Reader\Exception\SharedStringNotFoundException;
* This class implements the file-based caching strategy for shared strings. * This class implements the file-based caching strategy for shared strings.
* Shared strings are stored in small files (with a max number of strings per file). * Shared strings are stored in small files (with a max number of strings per file).
* This strategy is slower than an in-memory strategy but is used to avoid out of memory crashes. * This strategy is slower than an in-memory strategy but is used to avoid out of memory crashes.
*
* @package Box\Spout\Reader\XLSX\Helper\SharedStringsCaching
*/ */
class FileBasedStrategy implements CachingStrategyInterface class FileBasedStrategy implements CachingStrategyInterface
{ {
@ -51,18 +48,18 @@ class FileBasedStrategy implements CachingStrategyInterface
protected $inMemoryTempFileContents; protected $inMemoryTempFileContents;
/** /**
* @param string|null $tempFolder Temporary folder where the temporary files to store shared strings will be stored * @param string $tempFolder Temporary folder where the temporary files to store shared strings will be stored
* @param int $maxNumStringsPerTempFile Maximum number of strings that can be stored in one temp file * @param int $maxNumStringsPerTempFile Maximum number of strings that can be stored in one temp file
* @param HelperFactory $helperFactory Factory to create helpers
*/ */
public function __construct($tempFolder, $maxNumStringsPerTempFile) public function __construct($tempFolder, $maxNumStringsPerTempFile, $helperFactory)
{ {
$rootTempFolder = ($tempFolder) ?: sys_get_temp_dir(); $this->fileSystemHelper = $helperFactory->createFileSystemHelper($tempFolder);
$this->fileSystemHelper = new FileSystemHelper($rootTempFolder); $this->tempFolder = $this->fileSystemHelper->createFolder($tempFolder, uniqid('sharedstrings'));
$this->tempFolder = $this->fileSystemHelper->createFolder($rootTempFolder, uniqid('sharedstrings'));
$this->maxNumStringsPerTempFile = $maxNumStringsPerTempFile; $this->maxNumStringsPerTempFile = $maxNumStringsPerTempFile;
$this->globalFunctionsHelper = new GlobalFunctionsHelper(); $this->globalFunctionsHelper = $helperFactory->createGlobalFunctionsHelper();
$this->tempFilePointer = null; $this->tempFilePointer = null;
} }
@ -99,7 +96,8 @@ class FileBasedStrategy implements CachingStrategyInterface
*/ */
protected function getSharedStringTempFilePath($sharedStringIndex) protected function getSharedStringTempFilePath($sharedStringIndex)
{ {
$numTempFile = intval($sharedStringIndex / $this->maxNumStringsPerTempFile); $numTempFile = (int) ($sharedStringIndex / $this->maxNumStringsPerTempFile);
return $this->tempFolder . '/sharedstrings' . $numTempFile; return $this->tempFolder . '/sharedstrings' . $numTempFile;
} }
@ -117,13 +115,12 @@ class FileBasedStrategy implements CachingStrategyInterface
} }
} }
/** /**
* Returns the string located at the given index from the cache. * Returns the string located at the given index from the cache.
* *
* @param int $sharedStringIndex Index of the shared string in the sharedStrings.xml file * @param int $sharedStringIndex Index of the shared string in the sharedStrings.xml file
* @return string The shared string at the given index
* @throws \Box\Spout\Reader\Exception\SharedStringNotFoundException If no shared string found for the given index * @throws \Box\Spout\Reader\Exception\SharedStringNotFoundException If no shared string found for the given index
* @return string The shared string at the given index
*/ */
public function getStringAtIndex($sharedStringIndex) public function getStringAtIndex($sharedStringIndex)
{ {

View File

@ -1,6 +1,6 @@
<?php <?php
namespace Box\Spout\Reader\XLSX\Helper\SharedStringsCaching; namespace Box\Spout\Reader\XLSX\Manager\SharedStringsCaching;
use Box\Spout\Reader\Exception\SharedStringNotFoundException; use Box\Spout\Reader\Exception\SharedStringNotFoundException;
@ -9,8 +9,6 @@ use Box\Spout\Reader\Exception\SharedStringNotFoundException;
* *
* This class implements the in-memory caching strategy for shared strings. * This class implements the in-memory caching strategy for shared strings.
* This strategy is used when the number of unique strings is low, compared to the memory available. * This strategy is used when the number of unique strings is low, compared to the memory available.
*
* @package Box\Spout\Reader\XLSX\Helper\SharedStringsCaching
*/ */
class InMemoryStrategy implements CachingStrategyInterface class InMemoryStrategy implements CachingStrategyInterface
{ {
@ -58,8 +56,8 @@ class InMemoryStrategy implements CachingStrategyInterface
* Returns the string located at the given index from the cache. * Returns the string located at the given index from the cache.
* *
* @param int $sharedStringIndex Index of the shared string in the sharedStrings.xml file * @param int $sharedStringIndex Index of the shared string in the sharedStrings.xml file
* @return string The shared string at the given index
* @throws \Box\Spout\Reader\Exception\SharedStringNotFoundException If no shared string found for the given index * @throws \Box\Spout\Reader\Exception\SharedStringNotFoundException If no shared string found for the given index
* @return string The shared string at the given index
*/ */
public function getStringAtIndex($sharedStringIndex) public function getStringAtIndex($sharedStringIndex)
{ {

View File

@ -1,20 +1,20 @@
<?php <?php
namespace Box\Spout\Reader\XLSX\Helper; namespace Box\Spout\Reader\XLSX\Manager;
use Box\Spout\Common\Exception\IOException; use Box\Spout\Common\Exception\IOException;
use Box\Spout\Reader\Exception\XMLProcessingException; use Box\Spout\Reader\Exception\XMLProcessingException;
use Box\Spout\Reader\Wrapper\XMLReader; use Box\Spout\Reader\Wrapper\XMLReader;
use Box\Spout\Reader\XLSX\Helper\SharedStringsCaching\CachingStrategyFactory; use Box\Spout\Reader\XLSX\Creator\EntityFactory;
use Box\Spout\Reader\XLSX\Helper\SharedStringsCaching\CachingStrategyInterface; use Box\Spout\Reader\XLSX\Creator\HelperFactory;
use Box\Spout\Reader\XLSX\Manager\SharedStringsCaching\CachingStrategyFactory;
use Box\Spout\Reader\XLSX\Manager\SharedStringsCaching\CachingStrategyInterface;
/** /**
* Class SharedStringsHelper * Class SharedStringsManager
* This class provides helper functions for reading sharedStrings XML file * This class manages the shared strings defined in the associated XML file
*
* @package Box\Spout\Reader\XLSX\Helper
*/ */
class SharedStringsHelper class SharedStringsManager
{ {
/** Path of sharedStrings XML file inside the XLSX file */ /** Path of sharedStrings XML file inside the XLSX file */
const SHARED_STRINGS_XML_FILE_PATH = 'xl/sharedStrings.xml'; const SHARED_STRINGS_XML_FILE_PATH = 'xl/sharedStrings.xml';
@ -40,17 +40,32 @@ class SharedStringsHelper
/** @var string Temporary folder where the temporary files to store shared strings will be stored */ /** @var string Temporary folder where the temporary files to store shared strings will be stored */
protected $tempFolder; protected $tempFolder;
/** @var EntityFactory Factory to create entities */
protected $entityFactory;
/** @var HelperFactory $helperFactory Factory to create helpers */
protected $helperFactory;
/** @var CachingStrategyFactory Factory to create shared strings caching strategies */
protected $cachingStrategyFactory;
/** @var CachingStrategyInterface The best caching strategy for storing shared strings */ /** @var CachingStrategyInterface The best caching strategy for storing shared strings */
protected $cachingStrategy; protected $cachingStrategy;
/** /**
* @param string $filePath Path of the XLSX file being read * @param string $filePath Path of the XLSX file being read
* @param string|null|void $tempFolder Temporary folder where the temporary files to store shared strings will be stored * @param string $tempFolder Temporary folder where the temporary files to store shared strings will be stored
* @param EntityFactory $entityFactory Factory to create entities
* @param HelperFactory $helperFactory Factory to create helpers
* @param CachingStrategyFactory $cachingStrategyFactory Factory to create shared strings caching strategies
*/ */
public function __construct($filePath, $tempFolder = null) public function __construct($filePath, $tempFolder, $entityFactory, $helperFactory, $cachingStrategyFactory)
{ {
$this->filePath = $filePath; $this->filePath = $filePath;
$this->tempFolder = $tempFolder; $this->tempFolder = $tempFolder;
$this->entityFactory = $entityFactory;
$this->helperFactory = $helperFactory;
$this->cachingStrategyFactory = $cachingStrategyFactory;
} }
/** /**
@ -61,7 +76,7 @@ class SharedStringsHelper
public function hasSharedStrings() public function hasSharedStrings()
{ {
$hasSharedStrings = false; $hasSharedStrings = false;
$zip = new \ZipArchive(); $zip = $this->entityFactory->createZipArchive();
if ($zip->open($this->filePath) === true) { if ($zip->open($this->filePath) === true) {
$hasSharedStrings = ($zip->locateName(self::SHARED_STRINGS_XML_FILE_PATH) !== false); $hasSharedStrings = ($zip->locateName(self::SHARED_STRINGS_XML_FILE_PATH) !== false);
@ -81,12 +96,12 @@ class SharedStringsHelper
* The XML file can be really big with sheets containing a lot of data. That is why * The XML file can be really big with sheets containing a lot of data. That is why
* we need to use a XML reader that provides streaming like the XMLReader library. * we need to use a XML reader that provides streaming like the XMLReader library.
* *
* @return void
* @throws \Box\Spout\Common\Exception\IOException If sharedStrings.xml can't be read * @throws \Box\Spout\Common\Exception\IOException If sharedStrings.xml can't be read
* @return void
*/ */
public function extractSharedStrings() public function extractSharedStrings()
{ {
$xmlReader = new XMLReader(); $xmlReader = $this->entityFactory->createXMLReader();
$sharedStringIndex = 0; $sharedStringIndex = 0;
if ($xmlReader->openFileInZip($this->filePath, self::SHARED_STRINGS_XML_FILE_PATH) === false) { if ($xmlReader->openFileInZip($this->filePath, self::SHARED_STRINGS_XML_FILE_PATH) === false) {
@ -108,7 +123,6 @@ class SharedStringsHelper
} }
$this->cachingStrategy->closeCache(); $this->cachingStrategy->closeCache();
} catch (XMLProcessingException $exception) { } catch (XMLProcessingException $exception) {
throw new IOException("The sharedStrings.xml file is invalid and cannot be read. [{$exception->getMessage()}]"); throw new IOException("The sharedStrings.xml file is invalid and cannot be read. [{$exception->getMessage()}]");
} }
@ -120,8 +134,8 @@ class SharedStringsHelper
* Returns the shared strings unique count, as specified in <sst> tag. * Returns the shared strings unique count, as specified in <sst> tag.
* *
* @param \Box\Spout\Reader\Wrapper\XMLReader $xmlReader XMLReader instance * @param \Box\Spout\Reader\Wrapper\XMLReader $xmlReader XMLReader instance
* @return int|null Number of unique shared strings in the sharedStrings.xml file
* @throws \Box\Spout\Common\Exception\IOException If sharedStrings.xml is invalid and can't be read * @throws \Box\Spout\Common\Exception\IOException If sharedStrings.xml is invalid and can't be read
* @return int|null Number of unique shared strings in the sharedStrings.xml file
*/ */
protected function getSharedStringsUniqueCount($xmlReader) protected function getSharedStringsUniqueCount($xmlReader)
{ {
@ -140,7 +154,7 @@ class SharedStringsHelper
$uniqueCount = $xmlReader->getAttribute(self::XML_ATTRIBUTE_COUNT); $uniqueCount = $xmlReader->getAttribute(self::XML_ATTRIBUTE_COUNT);
} }
return ($uniqueCount !== null) ? intval($uniqueCount) : null; return ($uniqueCount !== null) ? (int) $uniqueCount : null;
} }
/** /**
@ -151,8 +165,8 @@ class SharedStringsHelper
*/ */
protected function getBestSharedStringsCachingStrategy($sharedStringsUniqueCount) protected function getBestSharedStringsCachingStrategy($sharedStringsUniqueCount)
{ {
return CachingStrategyFactory::getInstance() return $this->cachingStrategyFactory
->getBestCachingStrategy($sharedStringsUniqueCount, $this->tempFolder); ->createBestCachingStrategy($sharedStringsUniqueCount, $this->tempFolder, $this->helperFactory);
} }
/** /**
@ -193,6 +207,7 @@ class SharedStringsHelper
protected function shouldExtractTextNodeValue($textNode) protected function shouldExtractTextNodeValue($textNode)
{ {
$parentTagName = $textNode->parentNode->localName; $parentTagName = $textNode->parentNode->localName;
return ($parentTagName === self::XML_NODE_SI || $parentTagName === self::XML_NODE_R); return ($parentTagName === self::XML_NODE_SI || $parentTagName === self::XML_NODE_R);
} }
@ -205,6 +220,7 @@ class SharedStringsHelper
protected function shouldPreserveWhitespace($textNode) protected function shouldPreserveWhitespace($textNode)
{ {
$spaceValue = $textNode->getAttribute(self::XML_ATTRIBUTE_XML_SPACE); $spaceValue = $textNode->getAttribute(self::XML_ATTRIBUTE_XML_SPACE);
return ($spaceValue === self::XML_ATTRIBUTE_VALUE_PRESERVE); return ($spaceValue === self::XML_ATTRIBUTE_VALUE_PRESERVE);
} }
@ -212,8 +228,8 @@ class SharedStringsHelper
* Returns the shared string at the given index, using the previously chosen caching strategy. * Returns the shared string at the given index, using the previously chosen caching strategy.
* *
* @param int $sharedStringIndex Index of the shared string in the sharedStrings.xml file * @param int $sharedStringIndex Index of the shared string in the sharedStrings.xml file
* @return string The shared string at the given index
* @throws \Box\Spout\Reader\Exception\SharedStringNotFoundException If no shared string found for the given index * @throws \Box\Spout\Reader\Exception\SharedStringNotFoundException If no shared string found for the given index
* @return string The shared string at the given index
*/ */
public function getStringAtIndex($sharedStringIndex) public function getStringAtIndex($sharedStringIndex)
{ {

View File

@ -1,17 +1,15 @@
<?php <?php
namespace Box\Spout\Reader\XLSX\Helper; namespace Box\Spout\Reader\XLSX\Manager;
use Box\Spout\Reader\Wrapper\XMLReader; use Box\Spout\Reader\XLSX\Creator\EntityFactory;
use Box\Spout\Reader\XLSX\Sheet; use Box\Spout\Reader\XLSX\Sheet;
/** /**
* Class SheetHelper * Class SheetManager
* This class provides helper functions related to XLSX sheets * This class manages XLSX sheets
*
* @package Box\Spout\Reader\XLSX\Helper
*/ */
class SheetHelper class SheetManager
{ {
/** Paths of XML files relative to the XLSX file root */ /** Paths of XML files relative to the XLSX file root */
const WORKBOOK_XML_RELS_FILE_PATH = 'xl/_rels/workbook.xml.rels'; const WORKBOOK_XML_RELS_FILE_PATH = 'xl/_rels/workbook.xml.rels';
@ -33,27 +31,36 @@ class SheetHelper
/** @var string Path of the XLSX file being read */ /** @var string Path of the XLSX file being read */
protected $filePath; protected $filePath;
/** @var \Box\Spout\Reader\XLSX\ReaderOptions Reader's current options */ /** @var \Box\Spout\Common\Manager\OptionsManagerInterface Reader's options manager */
protected $options; protected $optionsManager;
/** @var \Box\Spout\Reader\XLSX\Helper\SharedStringsHelper Helper to work with shared strings */ /** @var \Box\Spout\Reader\XLSX\Manager\SharedStringsManager Manages shared strings */
protected $sharedStringsHelper; protected $sharedStringsManager;
/** @var \Box\Spout\Common\Helper\GlobalFunctionsHelper Helper to work with global functions */ /** @var \Box\Spout\Common\Helper\GlobalFunctionsHelper Helper to work with global functions */
protected $globalFunctionsHelper; protected $globalFunctionsHelper;
/** @var EntityFactory Factory to create entities */
protected $entityFactory;
/** @var \Box\Spout\Common\Helper\Escaper\XLSX Used to unescape XML data */
protected $escaper;
/** /**
* @param string $filePath Path of the XLSX file being read * @param string $filePath Path of the XLSX file being read
* @param \Box\Spout\Reader\XLSX\ReaderOptions $options Reader's current options * @param \Box\Spout\Common\Manager\OptionsManagerInterface $optionsManager Reader's options manager
* @param \Box\Spout\Reader\XLSX\Helper\SharedStringsHelper Helper to work with shared strings * @param \Box\Spout\Reader\XLSX\Manager\SharedStringsManager $sharedStringsManager Manages shared strings
* @param \Box\Spout\Common\Helper\GlobalFunctionsHelper $globalFunctionsHelper * @param \Box\Spout\Common\Helper\Escaper\XLSX $escaper Used to unescape XML data
* @param EntityFactory $entityFactory Factory to create entities
* @param mixed $sharedStringsManager
*/ */
public function __construct($filePath, $options, $sharedStringsHelper, $globalFunctionsHelper) public function __construct($filePath, $optionsManager, $sharedStringsManager, $escaper, $entityFactory)
{ {
$this->filePath = $filePath; $this->filePath = $filePath;
$this->options = $options; $this->optionsManager = $optionsManager;
$this->sharedStringsHelper = $sharedStringsHelper; $this->sharedStringsManager = $sharedStringsManager;
$this->globalFunctionsHelper = $globalFunctionsHelper; $this->escaper = $escaper;
$this->entityFactory = $entityFactory;
} }
/** /**
@ -68,7 +75,8 @@ class SheetHelper
$sheetIndex = 0; $sheetIndex = 0;
$activeSheetIndex = 0; // By default, the first sheet is active $activeSheetIndex = 0; // By default, the first sheet is active
$xmlReader = new XMLReader(); $xmlReader = $this->entityFactory->createXMLReader();
if ($xmlReader->openFileInZip($this->filePath, self::WORKBOOK_XML_FILE_PATH)) { if ($xmlReader->openFileInZip($this->filePath, self::WORKBOOK_XML_FILE_PATH)) {
while ($xmlReader->read()) { while ($xmlReader->read()) {
if ($xmlReader->isPositionedOnStartingNode(self::XML_NODE_WORKBOOK_VIEW)) { if ($xmlReader->isPositionedOnStartingNode(self::XML_NODE_WORKBOOK_VIEW)) {
@ -105,17 +113,18 @@ class SheetHelper
{ {
$sheetId = $xmlReaderOnSheetNode->getAttribute(self::XML_ATTRIBUTE_R_ID); $sheetId = $xmlReaderOnSheetNode->getAttribute(self::XML_ATTRIBUTE_R_ID);
$escapedSheetName = $xmlReaderOnSheetNode->getAttribute(self::XML_ATTRIBUTE_NAME); $escapedSheetName = $xmlReaderOnSheetNode->getAttribute(self::XML_ATTRIBUTE_NAME);
$sheetName = $this->escaper->unescape($escapedSheetName);
/** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */
$escaper = \Box\Spout\Common\Escaper\XLSX::getInstance();
$sheetName = $escaper->unescape($escapedSheetName);
$sheetDataXMLFilePath = $this->getSheetDataXMLFilePathForSheetId($sheetId); $sheetDataXMLFilePath = $this->getSheetDataXMLFilePathForSheetId($sheetId);
return new Sheet( return $this->entityFactory->createSheet(
$this->filePath, $sheetDataXMLFilePath, $this->filePath,
$sheetIndexZeroBased, $sheetName, $isSheetActive, $sheetDataXMLFilePath,
$this->options, $this->sharedStringsHelper $sheetIndexZeroBased,
$sheetName,
$isSheetActive,
$this->optionsManager,
$this->sharedStringsManager
); );
} }
@ -128,7 +137,7 @@ class SheetHelper
$sheetDataXMLFilePath = ''; $sheetDataXMLFilePath = '';
// find the file path of the sheet, by looking at the "workbook.xml.res" file // find the file path of the sheet, by looking at the "workbook.xml.res" file
$xmlReader = new XMLReader(); $xmlReader = $this->entityFactory->createXMLReader();
if ($xmlReader->openFileInZip($this->filePath, self::WORKBOOK_XML_RELS_FILE_PATH)) { if ($xmlReader->openFileInZip($this->filePath, self::WORKBOOK_XML_RELS_FILE_PATH)) {
while ($xmlReader->read()) { while ($xmlReader->read()) {
if ($xmlReader->isPositionedOnStartingNode(self::XML_NODE_RELATIONSHIP)) { if ($xmlReader->isPositionedOnStartingNode(self::XML_NODE_RELATIONSHIP)) {

View File

@ -1,16 +1,14 @@
<?php <?php
namespace Box\Spout\Reader\XLSX\Helper; namespace Box\Spout\Reader\XLSX\Manager;
use Box\Spout\Reader\Wrapper\XMLReader; use Box\Spout\Reader\XLSX\Creator\EntityFactory;
/** /**
* Class StyleHelper * Class StyleManager
* This class provides helper functions related to XLSX styles * This class manages XLSX styles
*
* @package Box\Spout\Reader\XLSX\Helper
*/ */
class StyleHelper class StyleManager
{ {
/** Paths of XML files relative to the XLSX file root */ /** Paths of XML files relative to the XLSX file root */
const STYLES_XML_FILE_PATH = 'xl/styles.xml'; const STYLES_XML_FILE_PATH = 'xl/styles.xml';
@ -53,6 +51,9 @@ class StyleHelper
/** @var string Path of the XLSX file being read */ /** @var string Path of the XLSX file being read */
protected $filePath; protected $filePath;
/** @var EntityFactory Factory to create entities */
protected $entityFactory;
/** @var array Array containing the IDs of built-in number formats indicating a date */ /** @var array Array containing the IDs of built-in number formats indicating a date */
protected $builtinNumFmtIdIndicatingDates; protected $builtinNumFmtIdIndicatingDates;
@ -67,10 +68,12 @@ class StyleHelper
/** /**
* @param string $filePath Path of the XLSX file being read * @param string $filePath Path of the XLSX file being read
* @param EntityFactory $entityFactory Factory to create entities
*/ */
public function __construct($filePath) public function __construct($filePath, $entityFactory)
{ {
$this->filePath = $filePath; $this->filePath = $filePath;
$this->entityFactory = $entityFactory;
$this->builtinNumFmtIdIndicatingDates = array_keys(self::$builtinNumFmtIdToNumFormatMapping); $this->builtinNumFmtIdIndicatingDates = array_keys(self::$builtinNumFmtIdToNumFormatMapping);
} }
@ -107,13 +110,12 @@ class StyleHelper
$this->customNumberFormats = []; $this->customNumberFormats = [];
$this->stylesAttributes = []; $this->stylesAttributes = [];
$xmlReader = new XMLReader(); $xmlReader = $this->entityFactory->createXMLReader();
if ($xmlReader->openFileInZip($this->filePath, self::STYLES_XML_FILE_PATH)) { if ($xmlReader->openFileInZip($this->filePath, self::STYLES_XML_FILE_PATH)) {
while ($xmlReader->read()) { while ($xmlReader->read()) {
if ($xmlReader->isPositionedOnStartingNode(self::XML_NODE_NUM_FMTS)) { if ($xmlReader->isPositionedOnStartingNode(self::XML_NODE_NUM_FMTS)) {
$this->extractNumberFormats($xmlReader); $this->extractNumberFormats($xmlReader);
} elseif ($xmlReader->isPositionedOnStartingNode(self::XML_NODE_CELL_XFS)) { } elseif ($xmlReader->isPositionedOnStartingNode(self::XML_NODE_CELL_XFS)) {
$this->extractStyleAttributes($xmlReader); $this->extractStyleAttributes($xmlReader);
} }
@ -135,7 +137,7 @@ class StyleHelper
{ {
while ($xmlReader->read()) { while ($xmlReader->read()) {
if ($xmlReader->isPositionedOnStartingNode(self::XML_NODE_NUM_FMT)) { if ($xmlReader->isPositionedOnStartingNode(self::XML_NODE_NUM_FMT)) {
$numFmtId = intval($xmlReader->getAttribute(self::XML_ATTRIBUTE_NUM_FMT_ID)); $numFmtId = (int) ($xmlReader->getAttribute(self::XML_ATTRIBUTE_NUM_FMT_ID));
$formatCode = $xmlReader->getAttribute(self::XML_ATTRIBUTE_FORMAT_CODE); $formatCode = $xmlReader->getAttribute(self::XML_ATTRIBUTE_FORMAT_CODE);
$this->customNumberFormats[$numFmtId] = $formatCode; $this->customNumberFormats[$numFmtId] = $formatCode;
} elseif ($xmlReader->isPositionedOnEndingNode(self::XML_NODE_NUM_FMTS)) { } elseif ($xmlReader->isPositionedOnEndingNode(self::XML_NODE_NUM_FMTS)) {
@ -158,10 +160,10 @@ class StyleHelper
while ($xmlReader->read()) { while ($xmlReader->read()) {
if ($xmlReader->isPositionedOnStartingNode(self::XML_NODE_XF)) { if ($xmlReader->isPositionedOnStartingNode(self::XML_NODE_XF)) {
$numFmtId = $xmlReader->getAttribute(self::XML_ATTRIBUTE_NUM_FMT_ID); $numFmtId = $xmlReader->getAttribute(self::XML_ATTRIBUTE_NUM_FMT_ID);
$normalizedNumFmtId = ($numFmtId !== null) ? intval($numFmtId) : null; $normalizedNumFmtId = ($numFmtId !== null) ? (int) $numFmtId : null;
$applyNumberFormat = $xmlReader->getAttribute(self::XML_ATTRIBUTE_APPLY_NUMBER_FORMAT); $applyNumberFormat = $xmlReader->getAttribute(self::XML_ATTRIBUTE_APPLY_NUMBER_FORMAT);
$normalizedApplyNumberFormat = ($applyNumberFormat !== null) ? !!$applyNumberFormat : null; $normalizedApplyNumberFormat = ($applyNumberFormat !== null) ? (bool) $applyNumberFormat : null;
$this->stylesAttributes[] = [ $this->stylesAttributes[] = [
self::XML_ATTRIBUTE_NUM_FMT_ID => $normalizedNumFmtId, self::XML_ATTRIBUTE_NUM_FMT_ID => $normalizedNumFmtId,

View File

@ -3,38 +3,46 @@
namespace Box\Spout\Reader\XLSX; namespace Box\Spout\Reader\XLSX;
use Box\Spout\Common\Exception\IOException; use Box\Spout\Common\Exception\IOException;
use Box\Spout\Reader\AbstractReader; use Box\Spout\Common\Helper\GlobalFunctionsHelper;
use Box\Spout\Reader\XLSX\Helper\SharedStringsHelper; use Box\Spout\Common\Manager\OptionsManagerInterface;
use Box\Spout\Reader\Common\Creator\EntityFactoryInterface;
use Box\Spout\Reader\Common\Entity\Options;
use Box\Spout\Reader\ReaderAbstract;
use Box\Spout\Reader\XLSX\Creator\EntityFactory;
use Box\Spout\Reader\XLSX\Creator\ManagerFactory;
/** /**
* Class Reader * Class Reader
* This class provides support to read data from a XLSX file * This class provides support to read data from a XLSX file
*
* @package Box\Spout\Reader\XLSX
*/ */
class Reader extends AbstractReader class Reader extends ReaderAbstract
{ {
/** @var ManagerFactory */
protected $managerFactory;
/** @var \ZipArchive */ /** @var \ZipArchive */
protected $zip; protected $zip;
/** @var \Box\Spout\Reader\XLSX\Helper\SharedStringsHelper Helper to work with shared strings */ /** @var \Box\Spout\Reader\XLSX\Manager\SharedStringsManager Manages shared strings */
protected $sharedStringsHelper; protected $sharedStringsManager;
/** @var SheetIterator To iterator over the XLSX sheets */ /** @var SheetIterator To iterator over the XLSX sheets */
protected $sheetIterator; protected $sheetIterator;
/** /**
* Returns the reader's current options * @param OptionsManagerInterface $optionsManager
* * @param GlobalFunctionsHelper $globalFunctionsHelper
* @return ReaderOptions * @param EntityFactoryInterface $entityFactory
* @param ManagerFactory $managerFactory
*/ */
protected function getOptions() public function __construct(
{ OptionsManagerInterface $optionsManager,
if (!isset($this->options)) { GlobalFunctionsHelper $globalFunctionsHelper,
$this->options = new ReaderOptions(); EntityFactoryInterface $entityFactory,
} ManagerFactory $managerFactory
return $this->options; ) {
parent::__construct($optionsManager, $globalFunctionsHelper, $entityFactory);
$this->managerFactory = $managerFactory;
} }
/** /**
@ -43,7 +51,8 @@ class Reader extends AbstractReader
*/ */
public function setTempFolder($tempFolder) public function setTempFolder($tempFolder)
{ {
$this->getOptions()->setTempFolder($tempFolder); $this->optionsManager->setOption(Options::TEMP_FOLDER, $tempFolder);
return $this; return $this;
} }
@ -63,23 +72,27 @@ class Reader extends AbstractReader
* and fetches all the available sheets. * and fetches all the available sheets.
* *
* @param string $filePath Path of the file to be read * @param string $filePath Path of the file to be read
* @return void
* @throws \Box\Spout\Common\Exception\IOException If the file at the given path or its content cannot be read * @throws \Box\Spout\Common\Exception\IOException If the file at the given path or its content cannot be read
* @throws \Box\Spout\Reader\Exception\NoSheetsFoundException If there are no sheets in the file * @throws \Box\Spout\Reader\Exception\NoSheetsFoundException If there are no sheets in the file
* @return void
*/ */
protected function openReader($filePath) protected function openReader($filePath)
{ {
$this->zip = new \ZipArchive(); /** @var EntityFactory $entityFactory */
$entityFactory = $this->entityFactory;
$this->zip = $entityFactory->createZipArchive();
if ($this->zip->open($filePath) === true) { if ($this->zip->open($filePath) === true) {
$this->sharedStringsHelper = new SharedStringsHelper($filePath, $this->getOptions()->getTempFolder()); $tempFolder = $this->optionsManager->getOption(Options::TEMP_FOLDER);
$this->sharedStringsManager = $this->managerFactory->createSharedStringsManager($filePath, $tempFolder, $entityFactory);
if ($this->sharedStringsHelper->hasSharedStrings()) { if ($this->sharedStringsManager->hasSharedStrings()) {
// Extracts all the strings from the sheets for easy access in the future // Extracts all the strings from the sheets for easy access in the future
$this->sharedStringsHelper->extractSharedStrings(); $this->sharedStringsManager->extractSharedStrings();
} }
$this->sheetIterator = new SheetIterator($filePath, $this->getOptions(), $this->sharedStringsHelper, $this->globalFunctionsHelper); $this->sheetIterator = $entityFactory->createSheetIterator($filePath, $this->optionsManager, $this->sharedStringsManager, $this->globalFunctionsHelper);
} else { } else {
throw new IOException("Could not open $filePath for reading."); throw new IOException("Could not open $filePath for reading.");
} }
@ -106,8 +119,8 @@ class Reader extends AbstractReader
$this->zip->close(); $this->zip->close();
} }
if ($this->sharedStringsHelper) { if ($this->sharedStringsManager) {
$this->sharedStringsHelper->cleanup(); $this->sharedStringsManager->cleanup();
} }
} }
} }

View File

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

View File

@ -3,18 +3,15 @@
namespace Box\Spout\Reader\XLSX; namespace Box\Spout\Reader\XLSX;
use Box\Spout\Common\Exception\IOException; use Box\Spout\Common\Exception\IOException;
use Box\Spout\Reader\Common\XMLProcessor;
use Box\Spout\Reader\Exception\XMLProcessingException; use Box\Spout\Reader\Exception\XMLProcessingException;
use Box\Spout\Reader\IteratorInterface; use Box\Spout\Reader\IteratorInterface;
use Box\Spout\Reader\Wrapper\XMLReader; use Box\Spout\Reader\Wrapper\XMLReader;
use Box\Spout\Reader\XLSX\Helper\CellHelper; use Box\Spout\Reader\XLSX\Helper\CellHelper;
use Box\Spout\Reader\XLSX\Helper\CellValueFormatter; use Box\Spout\Reader\XLSX\Helper\CellValueFormatter;
use Box\Spout\Reader\XLSX\Helper\StyleHelper;
use Box\Spout\Reader\Common\XMLProcessor;
/** /**
* Class RowIterator * Class RowIterator
*
* @package Box\Spout\Reader\XLSX
*/ */
class RowIterator implements IteratorInterface class RowIterator implements IteratorInterface
{ {
@ -45,9 +42,6 @@ class RowIterator implements IteratorInterface
/** @var Helper\CellValueFormatter Helper to format cell values */ /** @var Helper\CellValueFormatter Helper to format cell values */
protected $cellValueFormatter; protected $cellValueFormatter;
/** @var Helper\StyleHelper $styleHelper Helper to work with styles */
protected $styleHelper;
/** /**
* TODO: This variable can be deleted when row indices get preserved * TODO: This variable can be deleted when row indices get preserved
* @var int Number of read rows * @var int Number of read rows
@ -58,7 +52,7 @@ class RowIterator implements IteratorInterface
protected $currentlyProcessedRowData = []; protected $currentlyProcessedRowData = [];
/** @var array|null Buffer used to store the row data, while checking if there are more rows to read */ /** @var array|null Buffer used to store the row data, while checking if there are more rows to read */
protected $rowDataBuffer = null; protected $rowDataBuffer;
/** @var bool Indicates whether all rows have been read */ /** @var bool Indicates whether all rows have been read */
protected $hasReachedEndOfFile = false; protected $hasReachedEndOfFile = false;
@ -81,23 +75,21 @@ class RowIterator implements IteratorInterface
/** /**
* @param string $filePath Path of the XLSX file being read * @param string $filePath Path of the XLSX file being read
* @param string $sheetDataXMLFilePath Path of the sheet data XML file as in [Content_Types].xml * @param string $sheetDataXMLFilePath Path of the sheet data XML file as in [Content_Types].xml
* @param \Box\Spout\Reader\XLSX\ReaderOptions $options Reader's current options * @param bool $shouldPreserveEmptyRows Whether empty rows should be preserved
* @param Helper\SharedStringsHelper $sharedStringsHelper Helper to work with shared strings * @param XMLReader $xmlReader XML Reader
* @param XMLProcessor $xmlProcessor Helper to process XML files
* @param CellValueFormatter $cellValueFormatter Helper to format cell values
*/ */
public function __construct($filePath, $sheetDataXMLFilePath, $options, $sharedStringsHelper) public function __construct($filePath, $sheetDataXMLFilePath, $shouldPreserveEmptyRows, $xmlReader, $xmlProcessor, $cellValueFormatter)
{ {
$this->filePath = $filePath; $this->filePath = $filePath;
$this->sheetDataXMLFilePath = $this->normalizeSheetDataXMLFilePath($sheetDataXMLFilePath); $this->sheetDataXMLFilePath = $this->normalizeSheetDataXMLFilePath($sheetDataXMLFilePath);
$this->xmlReader = $xmlReader;
$this->xmlReader = new XMLReader(); $this->cellValueFormatter = $cellValueFormatter;
$this->shouldPreserveEmptyRows = $shouldPreserveEmptyRows;
$this->styleHelper = new StyleHelper($filePath);
$this->cellValueFormatter = new CellValueFormatter($sharedStringsHelper, $this->styleHelper, $options->shouldFormatDates());
$this->shouldPreserveEmptyRows = $options->shouldPreserveEmptyRows();
// Register all callbacks to process different nodes when reading the XML file // Register all callbacks to process different nodes when reading the XML file
$this->xmlProcessor = new XMLProcessor($this->xmlReader); $this->xmlProcessor = $xmlProcessor;
$this->xmlProcessor->registerCallback(self::XML_NODE_DIMENSION, XMLProcessor::NODE_TYPE_START, [$this, 'processDimensionStartingNode']); $this->xmlProcessor->registerCallback(self::XML_NODE_DIMENSION, XMLProcessor::NODE_TYPE_START, [$this, 'processDimensionStartingNode']);
$this->xmlProcessor->registerCallback(self::XML_NODE_ROW, XMLProcessor::NODE_TYPE_START, [$this, 'processRowStartingNode']); $this->xmlProcessor->registerCallback(self::XML_NODE_ROW, XMLProcessor::NODE_TYPE_START, [$this, 'processRowStartingNode']);
$this->xmlProcessor->registerCallback(self::XML_NODE_CELL, XMLProcessor::NODE_TYPE_START, [$this, 'processCellStartingNode']); $this->xmlProcessor->registerCallback(self::XML_NODE_CELL, XMLProcessor::NODE_TYPE_START, [$this, 'processCellStartingNode']);
@ -119,10 +111,10 @@ class RowIterator implements IteratorInterface
* Rewind the Iterator to the first element. * Rewind the Iterator to the first element.
* Initializes the XMLReader object that reads the associated sheet data. * Initializes the XMLReader object that reads the associated sheet data.
* The XMLReader is configured to be safe from billion laughs attack. * The XMLReader is configured to be safe from billion laughs attack.
* @link http://php.net/manual/en/iterator.rewind.php * @see http://php.net/manual/en/iterator.rewind.php
* *
* @return void
* @throws \Box\Spout\Common\Exception\IOException If the sheet data XML cannot be read * @throws \Box\Spout\Common\Exception\IOException If the sheet data XML cannot be read
* @return void
*/ */
public function rewind() public function rewind()
{ {
@ -144,7 +136,7 @@ class RowIterator implements IteratorInterface
/** /**
* Checks if current position is valid * Checks if current position is valid
* @link http://php.net/manual/en/iterator.valid.php * @see http://php.net/manual/en/iterator.valid.php
* *
* @return bool * @return bool
*/ */
@ -155,11 +147,11 @@ class RowIterator implements IteratorInterface
/** /**
* Move forward to next element. Reads data describing the next unprocessed row. * Move forward to next element. Reads data describing the next unprocessed row.
* @link http://php.net/manual/en/iterator.next.php * @see http://php.net/manual/en/iterator.next.php
* *
* @return void
* @throws \Box\Spout\Reader\Exception\SharedStringNotFoundException If a shared string was not found * @throws \Box\Spout\Reader\Exception\SharedStringNotFoundException If a shared string was not found
* @throws \Box\Spout\Common\Exception\IOException If unable to read the sheet data XML * @throws \Box\Spout\Common\Exception\IOException If unable to read the sheet data XML
* @return void
*/ */
public function next() public function next()
{ {
@ -194,9 +186,9 @@ class RowIterator implements IteratorInterface
} }
/** /**
* @return void
* @throws \Box\Spout\Reader\Exception\SharedStringNotFoundException If a shared string was not found * @throws \Box\Spout\Reader\Exception\SharedStringNotFoundException If a shared string was not found
* @throws \Box\Spout\Common\Exception\IOException If unable to read the sheet data XML * @throws \Box\Spout\Common\Exception\IOException If unable to read the sheet data XML
* @return void
*/ */
protected function readDataForNextRow() protected function readDataForNextRow()
{ {
@ -243,7 +235,7 @@ class RowIterator implements IteratorInterface
$spans = $xmlReader->getAttribute(self::XML_ATTRIBUTE_SPANS); // returns '1:5' for instance $spans = $xmlReader->getAttribute(self::XML_ATTRIBUTE_SPANS); // returns '1:5' for instance
if ($spans) { if ($spans) {
list(, $numberOfColumnsForRow) = explode(':', $spans); list(, $numberOfColumnsForRow) = explode(':', $spans);
$numberOfColumnsForRow = intval($numberOfColumnsForRow); $numberOfColumnsForRow = (int) $numberOfColumnsForRow;
} }
$this->currentlyProcessedRowData = ($numberOfColumnsForRow !== 0) ? array_fill(0, $numberOfColumnsForRow, '') : []; $this->currentlyProcessedRowData = ($numberOfColumnsForRow !== 0) ? array_fill(0, $numberOfColumnsForRow, '') : [];
@ -303,8 +295,8 @@ class RowIterator implements IteratorInterface
/** /**
* @param \Box\Spout\Reader\Wrapper\XMLReader $xmlReader XMLReader object, positioned on a "<row>" node * @param \Box\Spout\Reader\Wrapper\XMLReader $xmlReader XMLReader object, positioned on a "<row>" node
* @return int Row index
* @throws \Box\Spout\Common\Exception\InvalidArgumentException When the given cell index is invalid * @throws \Box\Spout\Common\Exception\InvalidArgumentException When the given cell index is invalid
* @return int Row index
*/ */
protected function getRowIndex($xmlReader) protected function getRowIndex($xmlReader)
{ {
@ -312,14 +304,14 @@ class RowIterator implements IteratorInterface
$currentRowIndex = $xmlReader->getAttribute(self::XML_ATTRIBUTE_ROW_INDEX); $currentRowIndex = $xmlReader->getAttribute(self::XML_ATTRIBUTE_ROW_INDEX);
return ($currentRowIndex !== null) ? return ($currentRowIndex !== null) ?
intval($currentRowIndex) : (int) $currentRowIndex :
$this->lastRowIndexProcessed + 1; $this->lastRowIndexProcessed + 1;
} }
/** /**
* @param \Box\Spout\Reader\Wrapper\XMLReader $xmlReader XMLReader object, positioned on a "<c>" node * @param \Box\Spout\Reader\Wrapper\XMLReader $xmlReader XMLReader object, positioned on a "<c>" node
* @return int Column index
* @throws \Box\Spout\Common\Exception\InvalidArgumentException When the given cell index is invalid * @throws \Box\Spout\Common\Exception\InvalidArgumentException When the given cell index is invalid
* @return int Column index
*/ */
protected function getColumnIndex($xmlReader) protected function getColumnIndex($xmlReader)
{ {
@ -353,7 +345,7 @@ class RowIterator implements IteratorInterface
/** /**
* Return the current element, either an empty row or from the buffer. * Return the current element, either an empty row or from the buffer.
* @link http://php.net/manual/en/iterator.current.php * @see http://php.net/manual/en/iterator.current.php
* *
* @return array|null * @return array|null
*/ */
@ -378,7 +370,7 @@ class RowIterator implements IteratorInterface
/** /**
* Return the key of the current element. Here, the row index. * Return the key of the current element. Here, the row index.
* @link http://php.net/manual/en/iterator.key.php * @see http://php.net/manual/en/iterator.key.php
* *
* @return int * @return int
*/ */
@ -392,7 +384,6 @@ class RowIterator implements IteratorInterface
$this->numReadRows; $this->numReadRows;
} }
/** /**
* Cleans up what was created to iterate over the object. * Cleans up what was created to iterate over the object.
* *

View File

@ -7,8 +7,6 @@ use Box\Spout\Reader\SheetInterface;
/** /**
* Class Sheet * Class Sheet
* Represents a sheet within a XLSX file * Represents a sheet within a XLSX file
*
* @package Box\Spout\Reader\XLSX
*/ */
class Sheet implements SheetInterface class Sheet implements SheetInterface
{ {
@ -25,17 +23,14 @@ class Sheet implements SheetInterface
protected $isActive; protected $isActive;
/** /**
* @param string $filePath Path of the XLSX file being read * @param RowIterator $rowIterator The corresponding row iterator
* @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 int $sheetIndex Index of the sheet, based on order in the workbook (zero-based)
* @param string $sheetName Name of the sheet * @param string $sheetName Name of the sheet
* @param bool $isSheetActive Whether the sheet was defined as active * @param bool $isSheetActive Whether the sheet was defined as active
* @param \Box\Spout\Reader\XLSX\ReaderOptions $options Reader's current options
* @param Helper\SharedStringsHelper Helper to work with shared strings
*/ */
public function __construct($filePath, $sheetDataXMLFilePath, $sheetIndex, $sheetName, $isSheetActive, $options, $sharedStringsHelper) public function __construct($rowIterator, $sheetIndex, $sheetName, $isSheetActive)
{ {
$this->rowIterator = new RowIterator($filePath, $sheetDataXMLFilePath, $options, $sharedStringsHelper); $this->rowIterator = $rowIterator;
$this->index = $sheetIndex; $this->index = $sheetIndex;
$this->name = $sheetName; $this->name = $sheetName;
$this->isActive = $isSheetActive; $this->isActive = $isSheetActive;

View File

@ -2,15 +2,13 @@
namespace Box\Spout\Reader\XLSX; namespace Box\Spout\Reader\XLSX;
use Box\Spout\Reader\IteratorInterface;
use Box\Spout\Reader\XLSX\Helper\SheetHelper;
use Box\Spout\Reader\Exception\NoSheetsFoundException; use Box\Spout\Reader\Exception\NoSheetsFoundException;
use Box\Spout\Reader\IteratorInterface;
use Box\Spout\Reader\XLSX\Manager\SheetManager;
/** /**
* Class SheetIterator * Class SheetIterator
* Iterate over XLSX sheet. * Iterate over XLSX sheet.
*
* @package Box\Spout\Reader\XLSX
*/ */
class SheetIterator implements IteratorInterface class SheetIterator implements IteratorInterface
{ {
@ -21,17 +19,13 @@ class SheetIterator implements IteratorInterface
protected $currentSheetIndex; protected $currentSheetIndex;
/** /**
* @param string $filePath Path of the file to be read * @param SheetManager $sheetManager Manages sheets
* @param \Box\Spout\Reader\XLSX\ReaderOptions $options Reader's current options
* @param \Box\Spout\Reader\XLSX\Helper\SharedStringsHelper $sharedStringsHelper
* @param \Box\Spout\Common\Helper\GlobalFunctionsHelper $globalFunctionsHelper
* @throws \Box\Spout\Reader\Exception\NoSheetsFoundException If there are no sheets in the file * @throws \Box\Spout\Reader\Exception\NoSheetsFoundException If there are no sheets in the file
*/ */
public function __construct($filePath, $options, $sharedStringsHelper, $globalFunctionsHelper) public function __construct($sheetManager)
{ {
// Fetch all available sheets // Fetch all available sheets
$sheetHelper = new SheetHelper($filePath, $options, $sharedStringsHelper, $globalFunctionsHelper); $this->sheets = $sheetManager->getSheets();
$this->sheets = $sheetHelper->getSheets();
if (count($this->sheets) === 0) { if (count($this->sheets) === 0) {
throw new NoSheetsFoundException('The file must contain at least one sheet.'); throw new NoSheetsFoundException('The file must contain at least one sheet.');
@ -40,7 +34,7 @@ class SheetIterator implements IteratorInterface
/** /**
* Rewind the Iterator to the first element * Rewind the Iterator to the first element
* @link http://php.net/manual/en/iterator.rewind.php * @see http://php.net/manual/en/iterator.rewind.php
* *
* @return void * @return void
*/ */
@ -51,7 +45,7 @@ class SheetIterator implements IteratorInterface
/** /**
* Checks if current position is valid * Checks if current position is valid
* @link http://php.net/manual/en/iterator.valid.php * @see http://php.net/manual/en/iterator.valid.php
* *
* @return bool * @return bool
*/ */
@ -62,7 +56,7 @@ class SheetIterator implements IteratorInterface
/** /**
* Move forward to next element * Move forward to next element
* @link http://php.net/manual/en/iterator.next.php * @see http://php.net/manual/en/iterator.next.php
* *
* @return void * @return void
*/ */
@ -79,7 +73,7 @@ class SheetIterator implements IteratorInterface
/** /**
* Return the current element * Return the current element
* @link http://php.net/manual/en/iterator.current.php * @see http://php.net/manual/en/iterator.current.php
* *
* @return \Box\Spout\Reader\XLSX\Sheet * @return \Box\Spout\Reader\XLSX\Sheet
*/ */
@ -90,7 +84,7 @@ class SheetIterator implements IteratorInterface
/** /**
* Return the key of the current element * Return the key of the current element
* @link http://php.net/manual/en/iterator.key.php * @see http://php.net/manual/en/iterator.key.php
* *
* @return int * @return int
*/ */

View File

@ -2,19 +2,17 @@
namespace Box\Spout\Writer\CSV\Manager; namespace Box\Spout\Writer\CSV\Manager;
use Box\Spout\Common\Manager\OptionsManagerAbstract;
use Box\Spout\Writer\Common\Entity\Options; use Box\Spout\Writer\Common\Entity\Options;
use Box\Spout\Writer\Common\Manager\OptionsManagerAbstract;
/** /**
* Class OptionsManager * Class OptionsManager
* CSV Writer options manager * CSV Writer options manager
*
* @package Box\Spout\Writer\CSV\Manager
*/ */
class OptionsManager extends OptionsManagerAbstract class OptionsManager extends OptionsManagerAbstract
{ {
/** /**
* @inheritdoc * {@inheritdoc}
*/ */
protected function getSupportedOptions() protected function getSupportedOptions()
{ {
@ -26,7 +24,7 @@ class OptionsManager extends OptionsManagerAbstract
} }
/** /**
* @inheritdoc * {@inheritdoc}
*/ */
protected function setDefaultOptions() protected function setDefaultOptions()
{ {

View File

@ -2,17 +2,15 @@
namespace Box\Spout\Writer\CSV; namespace Box\Spout\Writer\CSV;
use Box\Spout\Writer\WriterAbstract;
use Box\Spout\Common\Exception\IOException; use Box\Spout\Common\Exception\IOException;
use Box\Spout\Common\Helper\EncodingHelper; use Box\Spout\Common\Helper\EncodingHelper;
use Box\Spout\Writer\Common\Entity\Options; use Box\Spout\Writer\Common\Entity\Options;
use Box\Spout\Writer\Common\Entity\Row; use Box\Spout\Writer\Common\Entity\Row;
use Box\Spout\Writer\WriterAbstract;
/** /**
* Class Writer * Class Writer
* This class provides support to write data to CSV files * This class provides support to write data to CSV files
*
* @package Box\Spout\Writer\CSV
*/ */
class Writer extends WriterAbstract class Writer extends WriterAbstract
{ {
@ -35,6 +33,7 @@ class Writer extends WriterAbstract
public function setFieldDelimiter($fieldDelimiter) public function setFieldDelimiter($fieldDelimiter)
{ {
$this->optionsManager->setOption(Options::FIELD_DELIMITER, $fieldDelimiter); $this->optionsManager->setOption(Options::FIELD_DELIMITER, $fieldDelimiter);
return $this; return $this;
} }
@ -48,6 +47,7 @@ class Writer extends WriterAbstract
public function setFieldEnclosure($fieldEnclosure) public function setFieldEnclosure($fieldEnclosure)
{ {
$this->optionsManager->setOption(Options::FIELD_ENCLOSURE, $fieldEnclosure); $this->optionsManager->setOption(Options::FIELD_ENCLOSURE, $fieldEnclosure);
return $this; return $this;
} }
@ -61,6 +61,7 @@ class Writer extends WriterAbstract
public function setShouldAddBOM($shouldAddBOM) public function setShouldAddBOM($shouldAddBOM)
{ {
$this->optionsManager->setOption(Options::SHOULD_ADD_BOM, (bool) $shouldAddBOM); $this->optionsManager->setOption(Options::SHOULD_ADD_BOM, (bool) $shouldAddBOM);
return $this; return $this;
} }

View File

@ -3,32 +3,19 @@
namespace Box\Spout\Writer\Common\Creator; namespace Box\Spout\Writer\Common\Creator;
use Box\Spout\Writer\Common\Entity\Row; use Box\Spout\Writer\Common\Entity\Row;
use Box\Spout\Writer\Common\Entity\Cell;
use Box\Spout\Writer\Common\Entity\Sheet; use Box\Spout\Writer\Common\Entity\Sheet;
use Box\Spout\Writer\Common\Entity\Style\Style; use Box\Spout\Writer\Common\Entity\Style\Style;
use Box\Spout\Writer\Common\Entity\Workbook; use Box\Spout\Writer\Common\Entity\Workbook;
use Box\Spout\Writer\Common\Entity\Worksheet; use Box\Spout\Writer\Common\Entity\Worksheet;
use Box\Spout\Writer\Common\Manager\SheetManager;
/** /**
* Class EntityFactory * Class EntityFactory
* Factory to create entities * Factory to create entities
*
* @package Box\Spout\Writer\Common\Creator
*/ */
class EntityFactory class EntityFactory
{ {
/** @var ManagerFactory */
private $managerFactory;
/**
* EntityFactory constructor.
*
* @param ManagerFactory $managerFactory
*/
public function __construct(ManagerFactory $managerFactory)
{
$this->managerFactory = $managerFactory;
}
/** /**
* @return Workbook * @return Workbook
*/ */
@ -50,14 +37,31 @@ class EntityFactory
/** /**
* @param int $sheetIndex Index of the sheet, based on order in the workbook (zero-based) * @param int $sheetIndex Index of the sheet, based on order in the workbook (zero-based)
* @param string $associatedWorkbookId ID of the sheet's associated workbook * @param string $associatedWorkbookId ID of the sheet's associated workbook
* @param SheetManager $sheetManager To manage sheets
* @return Sheet * @return Sheet
*/ */
public function createSheet($sheetIndex, $associatedWorkbookId) public function createSheet($sheetIndex, $associatedWorkbookId, $sheetManager)
{ {
$sheetManager = $this->managerFactory->createSheetManager();
return new Sheet($sheetIndex, $associatedWorkbookId, $sheetManager); return new Sheet($sheetIndex, $associatedWorkbookId, $sheetManager);
} }
/**
* @param mixed $cellValue
* @return Cell
*/
public function createCell($cellValue)
{
return new Cell($cellValue);
}
/**
* @return \ZipArchive
*/
public function createZipArchive()
{
return new \ZipArchive();
}
/** /**
* @param array $cells * @param array $cells
* @param Style|null $style * @param Style|null $style

View File

@ -1,45 +0,0 @@
<?php
namespace Box\Spout\Writer\Common\Creator;
use Box\Spout\Common\Helper\StringHelper;
use Box\Spout\Writer\Common\Manager\CellManager;
use Box\Spout\Writer\Common\Manager\RowManager;
use Box\Spout\Writer\Common\Manager\SheetManager;
use Box\Spout\Writer\Common\Manager\Style\StyleMerger;
/**
* Class ManagerFactory
* Factory to create managers
*
* @package Box\Spout\Writer\Common\Creator
*/
class ManagerFactory
{
/**
* @return CellManager
*/
public function createCellManager()
{
$styleMerger = new StyleMerger();
return new CellManager($styleMerger);
}
/**
* @return RowManager
*/
public function createRowManager()
{
$styleMerger = new StyleMerger();
return new RowManager($styleMerger);
}
/**
* @return SheetManager
*/
public function createSheetManager()
{
$stringHelper = new StringHelper();
return new SheetManager($stringHelper);
}
}

View File

@ -2,19 +2,23 @@
namespace Box\Spout\Writer\Common\Creator; namespace Box\Spout\Writer\Common\Creator;
use Box\Spout\Writer\Common\Manager\OptionsManagerInterface; use Box\Spout\Common\Manager\OptionsManagerInterface;
use Box\Spout\Writer\Common\Manager\SheetManager;
use Box\Spout\Writer\Common\Manager\WorkbookManagerInterface; use Box\Spout\Writer\Common\Manager\WorkbookManagerInterface;
/** /**
* Interface InternalFactoryInterface * Interface ManagerFactoryInterface
*
* @package Box\Spout\Writer\Common\Creator
*/ */
interface InternalFactoryInterface interface ManagerFactoryInterface
{ {
/** /**
* @param OptionsManagerInterface $optionsManager * @param OptionsManagerInterface $optionsManager
* @return WorkbookManagerInterface * @return WorkbookManagerInterface
*/ */
public function createWorkbookManager(OptionsManagerInterface $optionsManager); public function createWorkbookManager(OptionsManagerInterface $optionsManager);
/**
* @return SheetManager
*/
public function createSheetManager();
} }

View File

@ -8,8 +8,6 @@ use Box\Spout\Writer\Common\Entity\Style\Color;
/** /**
* Class BorderBuilder * Class BorderBuilder
*
* @package \Box\Spout\Writer\Common\Creator\Style
*/ */
class BorderBuilder class BorderBuilder
{ {
@ -24,50 +22,54 @@ class BorderBuilder
} }
/** /**
* @param string|void $color Border A RGB color code * @param string $color Border A RGB color code
* @param string|void $width Border width @see BorderPart::allowedWidths * @param string $width Border width @see BorderPart::allowedWidths
* @param string|void $style Border style @see BorderPart::allowedStyles * @param string $style Border style @see BorderPart::allowedStyles
* @return BorderBuilder * @return BorderBuilder
*/ */
public function setBorderTop($color = Color::BLACK, $width = Border::WIDTH_MEDIUM, $style = Border::STYLE_SOLID) public function setBorderTop($color = Color::BLACK, $width = Border::WIDTH_MEDIUM, $style = Border::STYLE_SOLID)
{ {
$this->border->addPart(new BorderPart(Border::TOP, $color, $width, $style)); $this->border->addPart(new BorderPart(Border::TOP, $color, $width, $style));
return $this; return $this;
} }
/** /**
* @param string|void $color Border A RGB color code * @param string $color Border A RGB color code
* @param string|void $width Border width @see BorderPart::allowedWidths * @param string $width Border width @see BorderPart::allowedWidths
* @param string|void $style Border style @see BorderPart::allowedStyles * @param string $style Border style @see BorderPart::allowedStyles
* @return BorderBuilder * @return BorderBuilder
*/ */
public function setBorderRight($color = Color::BLACK, $width = Border::WIDTH_MEDIUM, $style = Border::STYLE_SOLID) public function setBorderRight($color = Color::BLACK, $width = Border::WIDTH_MEDIUM, $style = Border::STYLE_SOLID)
{ {
$this->border->addPart(new BorderPart(Border::RIGHT, $color, $width, $style)); $this->border->addPart(new BorderPart(Border::RIGHT, $color, $width, $style));
return $this; return $this;
} }
/** /**
* @param string|void $color Border A RGB color code * @param string $color Border A RGB color code
* @param string|void $width Border width @see BorderPart::allowedWidths * @param string $width Border width @see BorderPart::allowedWidths
* @param string|void $style Border style @see BorderPart::allowedStyles * @param string $style Border style @see BorderPart::allowedStyles
* @return BorderBuilder * @return BorderBuilder
*/ */
public function setBorderBottom($color = Color::BLACK, $width = Border::WIDTH_MEDIUM, $style = Border::STYLE_SOLID) public function setBorderBottom($color = Color::BLACK, $width = Border::WIDTH_MEDIUM, $style = Border::STYLE_SOLID)
{ {
$this->border->addPart(new BorderPart(Border::BOTTOM, $color, $width, $style)); $this->border->addPart(new BorderPart(Border::BOTTOM, $color, $width, $style));
return $this; return $this;
} }
/** /**
* @param string|void $color Border A RGB color code * @param string $color Border A RGB color code
* @param string|void $width Border width @see BorderPart::allowedWidths * @param string $width Border width @see BorderPart::allowedWidths
* @param string|void $style Border style @see BorderPart::allowedStyles * @param string $style Border style @see BorderPart::allowedStyles
* @return BorderBuilder * @return BorderBuilder
*/ */
public function setBorderLeft($color = Color::BLACK, $width = Border::WIDTH_MEDIUM, $style = Border::STYLE_SOLID) public function setBorderLeft($color = Color::BLACK, $width = Border::WIDTH_MEDIUM, $style = Border::STYLE_SOLID)
{ {
$this->border->addPart(new BorderPart(Border::LEFT, $color, $width, $style)); $this->border->addPart(new BorderPart(Border::LEFT, $color, $width, $style));
return $this; return $this;
} }

View File

@ -8,8 +8,6 @@ use Box\Spout\Writer\Common\Entity\Style\Style;
/** /**
* Class StyleBuilder * Class StyleBuilder
* Builder to create new styles * Builder to create new styles
*
* @package Box\Spout\Writer\Common\Creator\Style
*/ */
class StyleBuilder class StyleBuilder
{ {
@ -33,6 +31,7 @@ class StyleBuilder
public function setFontBold() public function setFontBold()
{ {
$this->style->setFontBold(); $this->style->setFontBold();
return $this; return $this;
} }
@ -45,6 +44,7 @@ class StyleBuilder
public function setFontItalic() public function setFontItalic()
{ {
$this->style->setFontItalic(); $this->style->setFontItalic();
return $this; return $this;
} }
@ -57,6 +57,7 @@ class StyleBuilder
public function setFontUnderline() public function setFontUnderline()
{ {
$this->style->setFontUnderline(); $this->style->setFontUnderline();
return $this; return $this;
} }
@ -69,6 +70,7 @@ class StyleBuilder
public function setFontStrikethrough() public function setFontStrikethrough()
{ {
$this->style->setFontStrikethrough(); $this->style->setFontStrikethrough();
return $this; return $this;
} }
@ -82,6 +84,7 @@ class StyleBuilder
public function setFontSize($fontSize) public function setFontSize($fontSize)
{ {
$this->style->setFontSize($fontSize); $this->style->setFontSize($fontSize);
return $this; return $this;
} }
@ -95,6 +98,7 @@ class StyleBuilder
public function setFontColor($fontColor) public function setFontColor($fontColor)
{ {
$this->style->setFontColor($fontColor); $this->style->setFontColor($fontColor);
return $this; return $this;
} }
@ -108,6 +112,7 @@ class StyleBuilder
public function setFontName($fontName) public function setFontName($fontName)
{ {
$this->style->setFontName($fontName); $this->style->setFontName($fontName);
return $this; return $this;
} }
@ -121,6 +126,7 @@ class StyleBuilder
public function setShouldWrapText($shouldWrap = true) public function setShouldWrapText($shouldWrap = true)
{ {
$this->style->setShouldWrapText($shouldWrap); $this->style->setShouldWrapText($shouldWrap);
return $this; return $this;
} }
@ -133,6 +139,7 @@ class StyleBuilder
public function setBorder(Border $border) public function setBorder(Border $border)
{ {
$this->style->setBorder($border); $this->style->setBorder($border);
return $this; return $this;
} }
@ -146,6 +153,7 @@ class StyleBuilder
public function setBackgroundColor($color) public function setBackgroundColor($color)
{ {
$this->style->setBackgroundColor($color); $this->style->setBackgroundColor($color);
return $this; return $this;
} }

View File

@ -8,8 +8,6 @@ use Box\Spout\Writer\Common\Manager\Style\StyleMerger;
/** /**
* Class Cell * Class Cell
*
* @package Box\Spout\Writer\Common\Entity
*/ */
class Cell class Cell
{ {
@ -48,13 +46,13 @@ class Cell
* The value of this cell * The value of this cell
* @var mixed|null * @var mixed|null
*/ */
protected $value = null; protected $value;
/** /**
* The cell type * The cell type
* @var int|null * @var int|null
*/ */
protected $type = null; protected $type;
/** /**
* The cell style * The cell style
@ -132,15 +130,18 @@ class Cell
{ {
if (CellHelper::isBoolean($value)) { if (CellHelper::isBoolean($value)) {
return self::TYPE_BOOLEAN; return self::TYPE_BOOLEAN;
} elseif (CellHelper::isEmpty($value)) {
return self::TYPE_EMPTY;
} elseif (CellHelper::isNumeric($this->getValue())) {
return self::TYPE_NUMERIC;
} elseif (CellHelper::isNonEmptyString($value)) {
return self::TYPE_STRING;
} else {
return self::TYPE_ERROR;
} }
if (CellHelper::isEmpty($value)) {
return self::TYPE_EMPTY;
}
if (CellHelper::isNumeric($this->getValue())) {
return self::TYPE_NUMERIC;
}
if (CellHelper::isNonEmptyString($value)) {
return self::TYPE_STRING;
}
return self::TYPE_ERROR;
} }
/** /**

View File

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

View File

@ -7,8 +7,6 @@ use Box\Spout\Writer\Common\Manager\SheetManager;
/** /**
* Class Sheet * Class Sheet
* External representation of a worksheet * External representation of a worksheet
*
* @package Box\Spout\Writer\Common\Entity
*/ */
class Sheet class Sheet
{ {
@ -29,7 +27,7 @@ class Sheet
/** /**
* @param int $sheetIndex Index of the sheet, based on order in the workbook (zero-based) * @param int $sheetIndex Index of the sheet, based on order in the workbook (zero-based)
* @param string $associatedWorkbookId ID of the sheet's associated workbook * @param string $associatedWorkbookId ID of the sheet's associated workbook
* @param SheetManager $sheetManager * @param SheetManager $sheetManager To manage sheets
*/ */
public function __construct($sheetIndex, $associatedWorkbookId, SheetManager $sheetManager) public function __construct($sheetIndex, $associatedWorkbookId, SheetManager $sheetManager)
{ {
@ -77,8 +75,8 @@ class Sheet
* *
* @api * @api
* @param string $name Name of the sheet * @param string $name Name of the sheet
* @return Sheet
* @throws \Box\Spout\Writer\Exception\InvalidSheetNameException If the sheet's name is invalid. * @throws \Box\Spout\Writer\Exception\InvalidSheetNameException If the sheet's name is invalid.
* @return Sheet
*/ */
public function setName($name) public function setName($name)
{ {

View File

@ -4,8 +4,6 @@ namespace Box\Spout\Writer\Common\Entity\Style;
/** /**
* Class Border * Class Border
*
* @package \Box\Spout\Writer\Common\Entity\Style
*/ */
class Border class Border
{ {
@ -28,7 +26,7 @@ class Border
private $parts = []; private $parts = [];
/** /**
* @param array|void $borderParts * @param array $borderParts
*/ */
public function __construct(array $borderParts = []) public function __construct(array $borderParts = [])
{ {
@ -37,7 +35,7 @@ class Border
/** /**
* @param string $name The name of the border part * @param string $name The name of the border part
* @return null|BorderPart * @return BorderPart|null
*/ */
public function getPart($name) public function getPart($name)
{ {
@ -81,6 +79,7 @@ class Border
public function addPart(BorderPart $borderPart) public function addPart(BorderPart $borderPart)
{ {
$this->parts[$borderPart->getName()] = $borderPart; $this->parts[$borderPart->getName()] = $borderPart;
return $this; return $this;
} }
} }

View File

@ -8,8 +8,6 @@ use Box\Spout\Writer\Exception\Border\InvalidWidthException;
/** /**
* Class BorderPart * Class BorderPart
*
* @package \Box\Spout\Writer\Common\Entity\Style
*/ */
class BorderPart class BorderPart
{ {
@ -41,7 +39,7 @@ class BorderPart
'solid', 'solid',
'dashed', 'dashed',
'dotted', 'dotted',
'double' 'double',
]; ];
/** /**

View File

@ -7,8 +7,6 @@ use Box\Spout\Writer\Exception\InvalidColorException;
/** /**
* Class Color * Class Color
* This class provides constants and functions to work with colors * This class provides constants and functions to work with colors
*
* @package Box\Spout\Writer\Common\Entity\Style
*/ */
class Color class Color
{ {
@ -52,8 +50,8 @@ class Color
* Throws an exception is the color component value is outside of bounds (0 - 255) * Throws an exception is the color component value is outside of bounds (0 - 255)
* *
* @param int $colorComponent * @param int $colorComponent
* @return void
* @throws \Box\Spout\Writer\Exception\InvalidColorException * @throws \Box\Spout\Writer\Exception\InvalidColorException
* @return void
*/ */
protected static function throwIfInvalidColorComponentValue($colorComponent) protected static function throwIfInvalidColorComponentValue($colorComponent)
{ {

View File

@ -5,8 +5,6 @@ namespace Box\Spout\Writer\Common\Entity\Style;
/** /**
* Class Style * Class Style
* Represents a style to be applied to a cell * Represents a style to be applied to a cell
*
* @package Box\Spout\Writer\Common\Entity\Style
*/ */
class Style class Style
{ {
@ -16,7 +14,7 @@ class Style
const DEFAULT_FONT_NAME = 'Arial'; const DEFAULT_FONT_NAME = 'Arial';
/** @var int|null Style ID */ /** @var int|null Style ID */
private $id = null; private $id;
/** @var bool Whether the font should be bold */ /** @var bool Whether the font should be bold */
private $fontBold = false; private $fontBold = false;
@ -62,18 +60,17 @@ class Style
private $hasSetWrapText = false; private $hasSetWrapText = false;
/** @var Border */ /** @var Border */
private $border = null; private $border;
/** @var bool Whether border properties should be applied */ /** @var bool Whether border properties should be applied */
private $shouldApplyBorder = false; private $shouldApplyBorder = false;
/** @var string Background color */ /** @var string Background color */
private $backgroundColor = null; private $backgroundColor;
/** @var bool */ /** @var bool */
private $hasSetBackgroundColor = false; private $hasSetBackgroundColor = false;
/** /**
* @return int|null * @return int|null
*/ */
@ -89,6 +86,7 @@ class Style
public function setId($id) public function setId($id)
{ {
$this->id = $id; $this->id = $id;
return $this; return $this;
} }
@ -108,6 +106,7 @@ class Style
{ {
$this->shouldApplyBorder = true; $this->shouldApplyBorder = true;
$this->border = $border; $this->border = $border;
return $this; return $this;
} }
@ -135,6 +134,7 @@ class Style
$this->fontBold = true; $this->fontBold = true;
$this->hasSetFontBold = true; $this->hasSetFontBold = true;
$this->shouldApplyFont = true; $this->shouldApplyFont = true;
return $this; return $this;
} }
@ -162,6 +162,7 @@ class Style
$this->fontItalic = true; $this->fontItalic = true;
$this->hasSetFontItalic = true; $this->hasSetFontItalic = true;
$this->shouldApplyFont = true; $this->shouldApplyFont = true;
return $this; return $this;
} }
@ -189,6 +190,7 @@ class Style
$this->fontUnderline = true; $this->fontUnderline = true;
$this->hasSetFontUnderline = true; $this->hasSetFontUnderline = true;
$this->shouldApplyFont = true; $this->shouldApplyFont = true;
return $this; return $this;
} }
@ -216,6 +218,7 @@ class Style
$this->fontStrikethrough = true; $this->fontStrikethrough = true;
$this->hasSetFontStrikethrough = true; $this->hasSetFontStrikethrough = true;
$this->shouldApplyFont = true; $this->shouldApplyFont = true;
return $this; return $this;
} }
@ -244,6 +247,7 @@ class Style
$this->fontSize = $fontSize; $this->fontSize = $fontSize;
$this->hasSetFontSize = true; $this->hasSetFontSize = true;
$this->shouldApplyFont = true; $this->shouldApplyFont = true;
return $this; return $this;
} }
@ -274,6 +278,7 @@ class Style
$this->fontColor = $fontColor; $this->fontColor = $fontColor;
$this->hasSetFontColor = true; $this->hasSetFontColor = true;
$this->shouldApplyFont = true; $this->shouldApplyFont = true;
return $this; return $this;
} }
@ -302,6 +307,7 @@ class Style
$this->fontName = $fontName; $this->fontName = $fontName;
$this->hasSetFontName = true; $this->hasSetFontName = true;
$this->shouldApplyFont = true; $this->shouldApplyFont = true;
return $this; return $this;
} }
@ -322,13 +328,14 @@ class Style
} }
/** /**
* @param bool|void $shouldWrap Should the text be wrapped * @param bool $shouldWrap Should the text be wrapped
* @return Style * @return Style
*/ */
public function setShouldWrapText($shouldWrap = true) public function setShouldWrapText($shouldWrap = true)
{ {
$this->shouldWrapText = $shouldWrap; $this->shouldWrapText = $shouldWrap;
$this->hasSetWrapText = true; $this->hasSetWrapText = true;
return $this; return $this;
} }
@ -357,6 +364,7 @@ class Style
{ {
$this->hasSetBackgroundColor = true; $this->hasSetBackgroundColor = true;
$this->backgroundColor = $color; $this->backgroundColor = $color;
return $this; return $this;
} }
@ -369,7 +377,6 @@ class Style
} }
/** /**
*
* @return bool Whether the background color should be applied * @return bool Whether the background color should be applied
*/ */
public function shouldApplyBackgroundColor() public function shouldApplyBackgroundColor()

View File

@ -5,8 +5,6 @@ namespace Box\Spout\Writer\Common\Entity;
/** /**
* Class Workbook * Class Workbook
* Entity describing a workbook * Entity describing a workbook
*
* @package Box\Spout\Writer\Common\Entity
*/ */
class Workbook class Workbook
{ {

View File

@ -5,15 +5,13 @@ namespace Box\Spout\Writer\Common\Entity;
/** /**
* Class Worksheet * Class Worksheet
* Entity describing a Worksheet * Entity describing a Worksheet
*
* @package Box\Spout\Writer\Common\Entity
*/ */
class Worksheet class Worksheet
{ {
/** @var string Path to the XML file that will contain the sheet data */ /** @var string Path to the XML file that will contain the sheet data */
private $filePath; private $filePath;
/** @var Resource Pointer to the sheet data file (e.g. xl/worksheets/sheet1.xml) */ /** @var resource Pointer to the sheet data file (e.g. xl/worksheets/sheet1.xml) */
private $filePointer; private $filePointer;
/** @var Sheet The "external" sheet */ /** @var Sheet The "external" sheet */
@ -49,7 +47,7 @@ class Worksheet
} }
/** /**
* @return Resource * @return resource
*/ */
public function getFilePointer() public function getFilePointer()
{ {
@ -57,7 +55,7 @@ class Worksheet
} }
/** /**
* @param Resource $filePointer * @param resource $filePointer
*/ */
public function setFilePointer($filePointer) public function setFilePointer($filePointer)
{ {

View File

@ -5,8 +5,6 @@ namespace Box\Spout\Writer\Common\Helper;
/** /**
* Class CellHelper * Class CellHelper
* This class provides helper functions when working with cells * This class provides helper functions when working with cells
*
* @package Box\Spout\Writer\Common\Helper
*/ */
class CellHelper class CellHelper
{ {
@ -36,8 +34,7 @@ class CellHelper
$cellIndex = chr($capitalAAsciiValue + $modulus) . $cellIndex; $cellIndex = chr($capitalAAsciiValue + $modulus) . $cellIndex;
// substracting 1 because it's zero-based // substracting 1 because it's zero-based
$columnIndex = intval($columnIndex / 26) - 1; $columnIndex = (int) ($columnIndex / 26) - 1;
} while ($columnIndex >= 0); } while ($columnIndex >= 0);
self::$columnIndexToCellIndexCache[$originalColumnIndex] = $cellIndex; self::$columnIndexToCellIndexCache[$originalColumnIndex] = $cellIndex;
@ -74,6 +71,7 @@ class CellHelper
public static function isNumeric($value) public static function isNumeric($value)
{ {
$valueType = gettype($value); $valueType = gettype($value);
return ($valueType === 'integer' || $valueType === 'double'); return ($valueType === 'integer' || $valueType === 'double');
} }

View File

@ -2,22 +2,20 @@
namespace Box\Spout\Writer\Common\Helper; namespace Box\Spout\Writer\Common\Helper;
use \Box\Spout\Common\Helper\FileSystemHelperInterface; use Box\Spout\Common\Helper\FileSystemHelperInterface;
/** /**
* Class FileSystemHelperInterface * Class FileSystemHelperInterface
* This interface describes helper functions to help with the file system operations * This interface describes helper functions to help with the file system operations
* like files/folders creation & deletion * like files/folders creation & deletion
*
* @package Box\Spout\Writer\Common\Helper
*/ */
interface FileSystemWithRootFolderHelperInterface extends FileSystemHelperInterface interface FileSystemWithRootFolderHelperInterface extends FileSystemHelperInterface
{ {
/** /**
* Creates all the folders needed to create a spreadsheet, as well as the files that won't change. * Creates all the folders needed to create a spreadsheet, as well as the files that won't change.
* *
* @return void
* @throws \Box\Spout\Common\Exception\IOException If unable to create at least one of the base folders * @throws \Box\Spout\Common\Exception\IOException If unable to create at least one of the base folders
* @return void
*/ */
public function createBaseFilesAndFolders(); public function createBaseFilesAndFolders();

View File

@ -2,11 +2,11 @@
namespace Box\Spout\Writer\Common\Helper; namespace Box\Spout\Writer\Common\Helper;
use Box\Spout\Writer\Common\Creator\EntityFactory;
/** /**
* Class ZipHelper * Class ZipHelper
* This class provides helper functions to create zip files * This class provides helper functions to create zip files
*
* @package Box\Spout\Writer\Common\Helper
*/ */
class ZipHelper class ZipHelper
{ {
@ -16,6 +16,17 @@ class ZipHelper
const EXISTING_FILES_SKIP = 'skip'; const EXISTING_FILES_SKIP = 'skip';
const EXISTING_FILES_OVERWRITE = 'overwrite'; const EXISTING_FILES_OVERWRITE = 'overwrite';
/** @var EntityFactory Factory to create entities */
private $entityFactory;
/**
* @param EntityFactory $entityFactory Factory to create entities
*/
public function __construct($entityFactory)
{
$this->entityFactory = $entityFactory;
}
/** /**
* Returns a new ZipArchive instance pointing at the given path. * Returns a new ZipArchive instance pointing at the given path.
* *
@ -24,7 +35,7 @@ class ZipHelper
*/ */
public function createZip($tmpFolderPath) public function createZip($tmpFolderPath)
{ {
$zip = new \ZipArchive(); $zip = $this->entityFactory->createZipArchive();
$zipFilePath = $tmpFolderPath . self::ZIP_EXTENSION; $zipFilePath = $tmpFolderPath . self::ZIP_EXTENSION;
$zip->open($zipFilePath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE); $zip->open($zipFilePath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE);
@ -52,7 +63,7 @@ class ZipHelper
* @param \ZipArchive $zip An opened zip archive object * @param \ZipArchive $zip An opened zip archive object
* @param string $rootFolderPath Path of the root folder that will be ignored in the archive tree. * @param string $rootFolderPath Path of the root folder that will be ignored in the archive tree.
* @param string $localFilePath Path of the file to be added, under the root folder * @param string $localFilePath Path of the file to be added, under the root folder
* @param string|void $existingFileMode Controls what to do when trying to add an existing file * @param string $existingFileMode Controls what to do when trying to add an existing file
* @return void * @return void
*/ */
public function addFileToArchive($zip, $rootFolderPath, $localFilePath, $existingFileMode = self::EXISTING_FILES_OVERWRITE) public function addFileToArchive($zip, $rootFolderPath, $localFilePath, $existingFileMode = self::EXISTING_FILES_OVERWRITE)
@ -77,7 +88,7 @@ class ZipHelper
* @param \ZipArchive $zip An opened zip archive object * @param \ZipArchive $zip An opened zip archive object
* @param string $rootFolderPath Path of the root folder that will be ignored in the archive tree. * @param string $rootFolderPath Path of the root folder that will be ignored in the archive tree.
* @param string $localFilePath Path of the file to be added, under the root folder * @param string $localFilePath Path of the file to be added, under the root folder
* @param string|void $existingFileMode Controls what to do when trying to add an existing file * @param string $existingFileMode Controls what to do when trying to add an existing file
* @return void * @return void
*/ */
public function addUncompressedFileToArchive($zip, $rootFolderPath, $localFilePath, $existingFileMode = self::EXISTING_FILES_OVERWRITE) public function addUncompressedFileToArchive($zip, $rootFolderPath, $localFilePath, $existingFileMode = self::EXISTING_FILES_OVERWRITE)
@ -130,7 +141,7 @@ class ZipHelper
/** /**
* @param \ZipArchive $zip An opened zip archive object * @param \ZipArchive $zip An opened zip archive object
* @param string $folderPath Path to the folder to be zipped * @param string $folderPath Path to the folder to be zipped
* @param string|void $existingFileMode Controls what to do when trying to add an existing file * @param string $existingFileMode Controls what to do when trying to add an existing file
* @return void * @return void
*/ */
public function addFolderToArchive($zip, $folderPath, $existingFileMode = self::EXISTING_FILES_OVERWRITE) public function addFolderToArchive($zip, $folderPath, $existingFileMode = self::EXISTING_FILES_OVERWRITE)
@ -171,6 +182,7 @@ class ZipHelper
protected function getNormalizedRealPath($path) protected function getNormalizedRealPath($path)
{ {
$realPath = realpath($path); $realPath = realpath($path);
return str_replace(DIRECTORY_SEPARATOR, '/', $realPath); return str_replace(DIRECTORY_SEPARATOR, '/', $realPath);
} }

View File

@ -9,8 +9,6 @@ use Box\Spout\Writer\Exception\InvalidSheetNameException;
/** /**
* Class SheetManager * Class SheetManager
* Sheet manager * Sheet manager
*
* @package Box\Spout\Writer\Common\Manager
*/ */
class SheetManager class SheetManager
{ {
@ -42,8 +40,8 @@ class SheetManager
* *
* @param string $name * @param string $name
* @param Sheet $sheet The sheet whose future name is checked * @param Sheet $sheet The sheet whose future name is checked
* @return void
* @throws \Box\Spout\Writer\Exception\InvalidSheetNameException If the sheet's name is invalid. * @throws \Box\Spout\Writer\Exception\InvalidSheetNameException If the sheet's name is invalid.
* @return void
*/ */
public function throwIfNameIsInvalid($name, Sheet $sheet) public function throwIfNameIsInvalid($name, Sheet $sheet)
{ {

View File

@ -8,8 +8,6 @@ use Box\Spout\Writer\Common\Entity\Style\Style;
/** /**
* Class StyleManager * Class StyleManager
* Manages styles to be applied to a cell * Manages styles to be applied to a cell
*
* @package Box\Spout\Writer\Common\Manager\Style
*/ */
class StyleManager implements StyleManagerInterface class StyleManager implements StyleManagerInterface
{ {
@ -47,7 +45,6 @@ class StyleManager implements StyleManagerInterface
return $this->styleRegistry->registerStyle($style); return $this->styleRegistry->registerStyle($style);
} }
/** /**
* Apply additional styles if the given row needs it. * Apply additional styles if the given row needs it.
* Typically, set "wrap text" if a cell contains a new line. * Typically, set "wrap text" if a cell contains a new line.

View File

@ -8,8 +8,6 @@ use Box\Spout\Writer\Common\Entity\Style\Style;
/** /**
* Interface StyleHManagernterface * Interface StyleHManagernterface
*
* @package Box\Spout\Writer\Common\Manager\Style
*/ */
interface StyleManagerInterface interface StyleManagerInterface
{ {

Some files were not shown because too many files have changed in this diff Show More