Compare commits

..
21 Commits
Author SHA1 Message Date
Adrien Loison 8459666841 Add "archived project" statement 2022-05-26 15:51:47 +02:00
Adrien Loison ec8d53b13c Make builds reproducible
By committing composer.lock, we make sure that dependencies are locked to a given version.
This ensures that builds are reproducible and deterministic.

Also, fixes some phpstan issues, that appeared with the latest version of PHPStan.
2022-05-26 15:49:00 +02:00
larsbonczek 0739e044da Fix encoding of Content-Disposition header
URL-encode file name in Content-Disposition header for file download.

fixes box/spout#878
2022-03-26 16:37:15 +01:00
Rodrigo Azevedo cc42c1d29f Use DateTimeInterface 2022-02-06 22:38:43 +01:00
Jörg Mönke 5926207012 Update GlobalFunctionsHelper.php
fix for php 8.1
2022-02-04 22:11:33 +01:00
Adrien Loison 550a6831f3 Update ci.yml
Launch CI on pull requests
2022-01-25 14:29:02 +01:00
Adrien Loison 6f1b67b39d PHPStan Level 4 2022-01-23 15:21:49 +01:00
Adrien Loison ea0a67d283 Remove var_dump 2022-01-21 14:31:32 +01:00
Adrien Loison e95e0eeefd PHPStan Level 3 2022-01-16 22:44:00 +01:00
Adrien Loison 64a09a748d More deprecations fixes 2022-01-13 23:04:26 +01:00
Adrien Loison 7517e5c4de Upgrade PHPUnit config 2022-01-13 23:04:26 +01:00
Adrien Loison e75f6f7301 Fix PHP 8.1 deprecations 2022-01-13 23:04:26 +01:00
Adrien Loison 27c6845b4b Upgrade to PHP 8.1 2022-01-13 23:04:26 +01:00
Adrien Loison 2499dc46b7 Integrate Coveralls 2022-01-13 14:46:46 +01:00
Adrien Loison 6b7366bb6f Upgrade PHP and dev dependencies
/!\ Removed PHP 7.2 support /!\

- PHPUnit 8 => 9 (+ fix the tests)
- PHP-CS-Fixer 2 => 3 (+ fix the code)
- Introduced PHP stan
2022-01-12 23:38:25 +01:00
Adrien Loison 6a10ec3586 Reduce number of jobs 2022-01-11 09:05:23 +01:00
Adrien Loison 9882bf0946 Fix errors on Windows 2022-01-11 09:05:23 +01:00
Adrien Loison 75c06807af Fix PHP Stan errors 2022-01-11 09:05:23 +01:00
Adrien Loison 0345b369c7 Fix tests with no locales + Apply CSFixer fixes 2022-01-11 09:05:23 +01:00
Adrien Loison f8595e9d63 Setup Github actions 2022-01-11 09:05:23 +01:00
Adrien Loison 9533accd73 Create FUNDING.yml 2021-06-07 12:33:43 +02:00
90 changed files with 4991 additions and 592 deletions

No files matched your search

+1
View File
@@ -0,0 +1 @@
github: adrilo
+270
View File
@@ -0,0 +1,270 @@
name: Spout CI
on: [push, pull_request]
jobs:
tests-on-php-latest:
strategy:
matrix:
operating-system: [ubuntu-latest, windows-latest, macos-latest]
runs-on: ${{ matrix.operating-system }}
name: Tests - PHP 8.1 on ${{ matrix.operating-system }}
env:
extensions: zip, xmlreader, dom
cache-key: cache-matrix-v1 # can be any string, change to clear the extension cache.
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup cache environment
id: extcache
uses: shivammathur/cache-extensions@v1
with:
php-version: '8.1'
extensions: ${{ env.extensions }}
key: ${{ env.cache-key }}
- name: Cache extensions
uses: actions/cache@v2
with:
path: ${{ steps.extcache.outputs.dir }}
key: ${{ steps.extcache.outputs.key }}
restore-keys: ${{ steps.extcache.outputs.key }}
- name: Setup PHP
uses: shivammathur/setup-php@v2 #https://github.com/shivammathur/setup-php
with:
php-version: '8.1'
extensions: ${{ env.extensions }}
- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache composer dependencies
uses: actions/cache@v2
with:
path: ${{ steps.composer-cache.outputs.dir }}
# Use composer.json for key, if composer.lock is not committed.
# key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader
- name: Test with phpunit
run: vendor/bin/phpunit --no-coverage
tests-on-older-php:
strategy:
matrix:
php-versions: ['7.3', '7.4', '8.0']
runs-on: ubuntu-latest
name: Tests - PHP ${{ matrix.php-versions }}
env:
extensions: zip, xmlreader, dom
cache-key: cache-matrix-v1 # can be any string, change to clear the extension cache.
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup cache environment
id: extcache
uses: shivammathur/cache-extensions@v1
with:
php-version: ${{ matrix.php-versions }}
extensions: ${{ env.extensions }}
key: ${{ env.cache-key }}
- name: Cache extensions
uses: actions/cache@v2
with:
path: ${{ steps.extcache.outputs.dir }}
key: ${{ steps.extcache.outputs.key }}
restore-keys: ${{ steps.extcache.outputs.key }}
- name: Setup PHP
uses: shivammathur/setup-php@v2 #https://github.com/shivammathur/setup-php
with:
php-version: ${{ matrix.php-versions }}
extensions: ${{ env.extensions }}
- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache composer dependencies
uses: actions/cache@v2
with:
path: ${{ steps.composer-cache.outputs.dir }}
# Use composer.json for key, if composer.lock is not committed.
# key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader
- name: Test with phpunit
run: vendor/bin/phpunit --no-coverage
code-coverage:
name: Code coverage
runs-on: ubuntu-latest
env:
extensions: zip, xmlreader, dom
cache-key: cache-single-v1 # can be any string, change to clear the extension cache.
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup cache environment
id: extcache
uses: shivammathur/cache-extensions@v1
with:
php-version: '8.1'
extensions: ${{ env.extensions }}
key: ${{ env.cache-key }}
- name: Cache extensions
uses: actions/cache@v2
with:
path: ${{ steps.extcache.outputs.dir }}
key: ${{ steps.extcache.outputs.key }}
restore-keys: ${{ steps.extcache.outputs.key }}
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
extensions: ${{ env.extensions }}
- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache composer dependencies
uses: actions/cache@v2
with:
path: ${{ steps.composer-cache.outputs.dir }}
# Use composer.json for key, if composer.lock is not committed.
# key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader
- name: Run Tests with Code Coverage
run: |
mkdir -p build/logs
vendor/bin/phpunit --coverage-clover=build/logs/clover.xml
- name: Upload coverage results to Coveralls
env:
COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
composer global require php-coveralls/php-coveralls
php-coveralls --coverage_clover=build/logs/clover.xml -v --exclude-no-stmt
coding-style:
name: Coding Style
runs-on: ubuntu-latest
env:
extensions: zip, xmlreader, dom
cache-key: cache-single-v1 # can be any string, change to clear the extension cache.
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup cache environment
id: extcache
uses: shivammathur/cache-extensions@v1
with:
php-version: '8.1'
extensions: ${{ env.extensions }}
key: ${{ env.cache-key }}
- name: Cache extensions
uses: actions/cache@v2
with:
path: ${{ steps.extcache.outputs.dir }}
key: ${{ steps.extcache.outputs.key }}
restore-keys: ${{ steps.extcache.outputs.key }}
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
extensions: ${{ env.extensions }}
- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache composer dependencies
uses: actions/cache@v2
with:
path: ${{ steps.composer-cache.outputs.dir }}
# Use composer.json for key, if composer.lock is not committed.
# key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader
- name: Run PHP-CS-Fixer
run: vendor/bin/php-cs-fixer fix --verbose --diff --dry-run
static-analysis:
name: Static Analysis
runs-on: ubuntu-latest
env:
extensions: zip, xmlreader, dom
cache-key: cache-single-v1 # can be any string, change to clear the extension cache.
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup cache environment
id: extcache
uses: shivammathur/cache-extensions@v1
with:
php-version: '8.1'
extensions: ${{ env.extensions }}
key: ${{ env.cache-key }}
- name: Cache extensions
uses: actions/cache@v2
with:
path: ${{ steps.extcache.outputs.dir }}
key: ${{ steps.extcache.outputs.key }}
restore-keys: ${{ steps.extcache.outputs.key }}
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
extensions: ${{ env.extensions }}
tools: phpstan
- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache composer dependencies
uses: actions/cache@v2
with:
path: ${{ steps.composer-cache.outputs.dir }}
# Use composer.json for key, if composer.lock is not committed.
# key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader
- name: Static Analysis using PHPStan
run: ./vendor/bin/phpstan analyse -c phpstan.neon --no-progress
+1 -2
View File
@@ -4,6 +4,5 @@
/tests/resources/generated /tests/resources/generated
/tests/coverage /tests/coverage
/vendor /vendor
/composer.lock /.php-cs-fixer.cache
/.php_cs.cache
/.phpunit.result.cache /.phpunit.result.cache
+13 -18
View File
@@ -1,6 +1,12 @@
<?php <?php
$config = PhpCsFixer\Config::create() $finder = PhpCsFixer\Finder::create()
->in(__DIR__)
->name('*.php')
->exclude('vendor');
$config = new PhpCsFixer\Config();
return $config
->setRiskyAllowed(true) ->setRiskyAllowed(true)
->setRules([ ->setRules([
'@Symfony' => true, '@Symfony' => true,
@@ -13,13 +19,13 @@ $config = PhpCsFixer\Config::create()
'declare_equal_normalize' => ['space' => 'single'], 'declare_equal_normalize' => ['space' => 'single'],
'heredoc_to_nowdoc' => true, 'heredoc_to_nowdoc' => true,
'increment_style' => ['style' => 'post'], 'increment_style' => ['style' => 'post'],
'is_null' => ['use_yoda_style' => false], 'is_null' => true,
'method_argument_space' => ['ensure_fully_multiline' => true], 'method_argument_space' => ['on_multiline' => 'ensure_fully_multiline'],
'modernize_types_casting' => true, 'modernize_types_casting' => true,
'no_break_comment' => ['comment_text' => 'do nothing'], 'no_break_comment' => ['comment_text' => 'do nothing'],
'no_empty_phpdoc' => false, 'no_empty_phpdoc' => false,
'no_null_property_initialization' => true, 'no_null_property_initialization' => true,
'no_short_echo_tag' => true, 'echo_tag_syntax' => false,
'no_superfluous_elseif' => true, 'no_superfluous_elseif' => true,
'no_superfluous_phpdoc_tags' => false, 'no_superfluous_phpdoc_tags' => false,
'no_unneeded_control_parentheses' => ['statements' => ['break', 'clone', 'continue', 'echo_print', 'switch_case', 'yield']], 'no_unneeded_control_parentheses' => ['statements' => ['break', 'clone', 'continue', 'echo_print', 'switch_case', 'yield']],
@@ -37,23 +43,12 @@ $config = PhpCsFixer\Config::create()
'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'], 'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'],
'phpdoc_separation' => false, 'phpdoc_separation' => false,
'protected_to_private' => true, 'protected_to_private' => true,
'psr4' => true, 'psr_autoloading' => true,
'return_type_declaration' => ['space_before' => 'one'], 'return_type_declaration' => ['space_before' => 'one'],
'semicolon_after_instruction' => true, 'semicolon_after_instruction' => true,
'simplified_null_return' => false, 'simplified_null_return' => false,
'single_line_comment_style' => ['comment_types' => ['hash']], 'single_line_comment_style' => ['comment_types' => ['hash']],
'strict_comparison' => true, 'strict_comparison' => true,
'yoda_style' => ['equal' => false, 'identical' => false], 'yoda_style' => ['equal' => false, 'identical' => false],
]); ])
->setFinder($finder);
$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;
-57
View File
@@ -1,57 +0,0 @@
filter:
excluded_paths: [vendor/*, tests/*]
tools:
external_code_coverage:
timeout: 600 # Wait 10 minutes for results
runs: 1 # Merge results for the 7.1 job
php_mess_detector: true
php_code_sniffer:
config:
standard: PSR4
filter:
paths: ['src']
sensiolabs_security_checker: true
php_pdepend: true
php_loc:
enabled: true
filter:
paths: ['src']
php_cpd: false # Must be disabled to use php_sim instead
php_sim:
enabled: true
filter:
paths: ['src']
build_failure_conditions:
- 'project.metric("scrutinizer.quality", < 9)' # Code Quality Rating drops below 9
- 'project.metric_change("scrutinizer.test_coverage", < -0.005)' # Code Coverage decreased by more than 0.5%
- 'project.metric("scrutinizer.test_coverage", < 0.97)' # Code Coverage drops below 97%
checks:
php:
remove_extra_empty_lines: true
remove_php_closing_tag: true
remove_trailing_whitespace: true
fix_use_statements:
remove_unused: true
preserve_multiple: false
preserve_blanklines: true
fix_php_opening_tag: true
fix_linefeed: true
fix_line_ending: true
fix_identation_4spaces: true
fix_doc_comments: true
uppercase_constants: true
use_self_instead_of_fqcn: true
simplify_boolean_return: true
return_doc_comments: true
return_doc_comment_if_not_inferrable: true
phpunit_assertions: true
parameters_in_camelcaps: true
parameter_doc_comments: true
param_doc_comment_if_not_inferrable: true
optional_parameters_at_the_end: true
newline_at_end_of_file: true
encourage_single_quotes: true
-61
View File
@@ -1,61 +0,0 @@
dist: bionic
sudo: false
language: php
matrix:
include:
- php: 7.2
env: WITH_PHPUNIT=true
- php: 7.3
env: WITH_PHPUNIT=true
- php: 7.3
env: WITH_PHPUNIT=true WITH_COVERAGE=true
- php: 7.4
env: WITH_PHPUNIT=true
- php: 8.0
env: WITH_PHPUNIT=true
cache:
directories:
- $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:
- composer install --no-interaction --prefer-source
before_script:
- mkdir -p "$HOME/.php-cs-fixer"
- mkdir -p build/logs
script:
- |
if [[ "$WITH_CS" == "true" ]]; then
vendor/bin/php-cs-fixer fix --config=.php_cs.dist --verbose --diff --dry-run --diff-format=udiff
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:
- |
if [[ "$WITH_COVERAGE" == "true" ]]; then
wget https://scrutinizer-ci.com/ocular.phar
php ocular.phar code-coverage:upload --format=php-clover build/logs/coverage.clover
fi
+19 -9
View File
@@ -1,12 +1,25 @@
# Spout # Spout
[![Latest Stable Version](https://poser.pugx.org/box/spout/v/stable)](https://packagist.org/packages/box/spout) [![Latest Stable Version](https://poser.pugx.org/box/spout/v/stable)](https://packagist.org/packages/box/spout)
[![Project Status](https://opensource.box.com/badges/active.svg)](https://opensource.box.com/badges) [![Project Status](https://opensource.box.com/badges/inactive.svg)](https://opensource.box.com/badges)
[![Build Status](https://travis-ci.org/box/spout.svg?branch=master)](https://travis-ci.org/box/spout) [![example workflow](https://github.com/box/spout/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/box/spout/actions/workflows/ci.yml?query=branch%3Amaster)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/box/spout/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/box/spout/?branch=master) [![Coverage Status](https://coveralls.io/repos/github/box/spout/badge.svg?branch=master)](https://coveralls.io/github/box/spout?branch=master)
[![Code Coverage](https://scrutinizer-ci.com/g/box/spout/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/box/spout/?branch=master)
[![Total Downloads](https://poser.pugx.org/box/spout/downloads)](https://packagist.org/packages/box/spout) [![Total Downloads](https://poser.pugx.org/box/spout/downloads)](https://packagist.org/packages/box/spout)
## 🪦 Archived project 🪦
This project has been archived and is no longer maintained. No bug fix and no additional features will be added.<br>
You won't be able to submit new issues or pull requests, and no additional features will be added
You can still use Spout as is in your projects though :)
> Thanks to everyone who contributed to this project, from a typo fix to the new cool feature.<br>
> It was great to see the involvement of this community!
<br>
## About
Spout is a PHP library to read and write spreadsheet files (CSV, XLSX and ODS), in a fast and scalable way. Spout is a PHP library to read and write spreadsheet files (CSV, XLSX and ODS), in a fast and scalable way.
Unlike other file readers or writers, it is capable of processing very large files, while keeping the memory usage really low (less than 3MB). Unlike other file readers or writers, it is capable of processing very large files, while keeping the memory usage really low (less than 3MB).
@@ -38,17 +51,14 @@ If you just want to check that everything is working as expected, executing the
For information, the performance tests take about 10 minutes to run (processing 1 million rows files is not a quick thing). For information, the performance tests take about 10 minutes to run (processing 1 million rows files is not a quick thing).
> Performance tests status: [![Build Status](https://travis-ci.org/box/spout.svg?branch=perf-tests)](https://travis-ci.org/box/spout)
## Support ## Support
You can ask questions, submit new features ideas or discuss Spout in the chat room:<br> Spout is no longer actively supported. You can still ask questions, or discuss about it in the chat room:<br>
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/box/spout?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/box/spout?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
## Copyright and License ## Copyright and License
Copyright 2017 Box, Inc. All rights reserved. Copyright 2022 Box, Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
-35
View File
@@ -1,35 +0,0 @@
build: false
clone_depth: 1
environment:
PHP_CHOCO_VERSION: 7.2.0
PHP_CACHE_DIR: C:\tools\php
cache:
- '%PHP_CACHE_DIR% -> appveyor.yml'
init:
- SET PATH=%PHP_CACHE_DIR%;%PATH%
- SET COMPOSER_CACHE_DIR=%PHP_CACHE_DIR%
- SET COMPOSER_NO_INTERACTION=1
- SET PHP=0
- SET ANSICON=121x90 (121x90)
install:
- IF EXIST %PHP_CACHE_DIR% (SET PHP=1)
- IF %PHP%==0 cinst php -y --version %PHP_CHOCO_VERSION% --params "/InstallDir:%PHP_CACHE_DIR%"
- IF %PHP%==0 cinst composer -y --ia "/DEV=%PHP_CACHE_DIR%"
- cd %PHP_CACHE_DIR%
- IF %PHP%==0 copy php.ini-production php.ini
- IF %PHP%==0 echo extension_dir=ext >> php.ini
- IF %PHP%==0 echo extension=php_fileinfo.dll >> php.ini
- IF %PHP%==0 echo extension=php_mbstring.dll >> php.ini
- IF %PHP%==0 echo extension=php_openssl.dll >> php.ini
- php -v
- IF %PHP%==0 (composer --version) ELSE (composer self-update)
- cd %APPVEYOR_BUILD_FOLDER%
- composer install --prefer-dist --no-progress
test_script:
- cd %APPVEYOR_BUILD_FOLDER%
- vendor\bin\phpunit --colors=always
+5 -4
View File
@@ -12,14 +12,15 @@
} }
], ],
"require": { "require": {
"php": ">=7.2.0", "php": ">=7.3.0",
"ext-zip": "*", "ext-zip": "*",
"ext-xmlreader": "*", "ext-xmlreader": "*",
"ext-dom": "*" "ext-dom": "*"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^8", "phpunit/phpunit": "^9",
"friendsofphp/php-cs-fixer": "^2" "friendsofphp/php-cs-fixer": "^3",
"phpstan/phpstan": "^1"
}, },
"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)",
@@ -37,7 +38,7 @@
}, },
"config": { "config": {
"platform": { "platform": {
"php": "7.2" "php": "7.3"
} }
} }
} }
Generated
+4196
View File
File diff suppressed because it is too large. Load diff
+9
View File
@@ -0,0 +1,9 @@
parameters:
level: 4
paths:
- src
- tests
excludePaths:
# Exclude these files that are OK
- src/Spout/Reader/Common/Creator/ReaderEntityFactory.php
- src/Spout/Writer/Common/Creator/WriterEntityFactory.php
+5 -7
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/8.5/phpunit.xsd" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
bootstrap="tests/bootstrap.php" bootstrap="tests/bootstrap.php"
colors="true" colors="true"
convertErrorsToExceptions="false" convertErrorsToExceptions="false"
@@ -13,11 +13,9 @@
</php> </php>
<testsuites> <testsuites>
<testsuite name="unit-tests"> <testsuite name="unit-tests">
<directory>tests/</directory> <directory>tests/</directory>
</testsuite> </testsuite>
</testsuites> </testsuites>
<groups> <groups>
@@ -26,13 +24,13 @@
</exclude> </exclude>
</groups> </groups>
<filter> <coverage>
<whitelist> <include>
<directory suffix=".php">src/</directory> <directory suffix=".php">src/</directory>
</include>
<exclude> <exclude>
<directory>src/Spout/Autoloader</directory> <directory>src/Spout/Autoloader</directory>
</exclude> </exclude>
</whitelist> </coverage>
</filter>
</phpunit> </phpunit>
+7 -7
View File
@@ -13,38 +13,38 @@ class Cell
/** /**
* Numeric cell type (whole numbers, fractional numbers, dates) * Numeric cell type (whole numbers, fractional numbers, dates)
*/ */
const TYPE_NUMERIC = 0; public const TYPE_NUMERIC = 0;
/** /**
* String (text) cell type * String (text) cell type
*/ */
const TYPE_STRING = 1; public const TYPE_STRING = 1;
/** /**
* Formula cell type * Formula cell type
* Not used at the moment * Not used at the moment
*/ */
const TYPE_FORMULA = 2; public const TYPE_FORMULA = 2;
/** /**
* Empty cell type * Empty cell type
*/ */
const TYPE_EMPTY = 3; public const TYPE_EMPTY = 3;
/** /**
* Boolean cell type * Boolean cell type
*/ */
const TYPE_BOOLEAN = 4; public const TYPE_BOOLEAN = 4;
/** /**
* Date cell type * Date cell type
*/ */
const TYPE_DATE = 5; public const TYPE_DATE = 5;
/** /**
* Error cell type * Error cell type
*/ */
const TYPE_ERROR = 6; public const TYPE_ERROR = 6;
/** /**
* The value of this cell * The value of this cell
+12 -12
View File
@@ -7,20 +7,20 @@ namespace Box\Spout\Common\Entity\Style;
*/ */
class Border class Border
{ {
const LEFT = 'left'; public const LEFT = 'left';
const RIGHT = 'right'; public const RIGHT = 'right';
const TOP = 'top'; public const TOP = 'top';
const BOTTOM = 'bottom'; public const BOTTOM = 'bottom';
const STYLE_NONE = 'none'; public const STYLE_NONE = 'none';
const STYLE_SOLID = 'solid'; public const STYLE_SOLID = 'solid';
const STYLE_DASHED = 'dashed'; public const STYLE_DASHED = 'dashed';
const STYLE_DOTTED = 'dotted'; public const STYLE_DOTTED = 'dotted';
const STYLE_DOUBLE = 'double'; public const STYLE_DOUBLE = 'double';
const WIDTH_THIN = 'thin'; public const WIDTH_THIN = 'thin';
const WIDTH_MEDIUM = 'medium'; public const WIDTH_MEDIUM = 'medium';
const WIDTH_THICK = 'thick'; public const WIDTH_THICK = 'thick';
/** @var array A list of BorderPart objects for this border. */ /** @var array A list of BorderPart objects for this border. */
private $parts = []; private $parts = [];
@@ -8,10 +8,10 @@ namespace Box\Spout\Common\Entity\Style;
*/ */
abstract class CellAlignment abstract class CellAlignment
{ {
const LEFT = 'left'; public const LEFT = 'left';
const RIGHT = 'right'; public const RIGHT = 'right';
const CENTER = 'center'; public const CENTER = 'center';
const JUSTIFY = 'justify'; public const JUSTIFY = 'justify';
private static $VALID_ALIGNMENTS = [ private static $VALID_ALIGNMENTS = [
self::LEFT => 1, self::LEFT => 1,
+12 -12
View File
@@ -11,18 +11,18 @@ use Box\Spout\Common\Exception\InvalidColorException;
abstract class Color abstract class Color
{ {
/** Standard colors - based on Office Online */ /** Standard colors - based on Office Online */
const BLACK = '000000'; public const BLACK = '000000';
const WHITE = 'FFFFFF'; public const WHITE = 'FFFFFF';
const RED = 'FF0000'; public const RED = 'FF0000';
const DARK_RED = 'C00000'; public const DARK_RED = 'C00000';
const ORANGE = 'FFC000'; public const ORANGE = 'FFC000';
const YELLOW = 'FFFF00'; public const YELLOW = 'FFFF00';
const LIGHT_GREEN = '92D040'; public const LIGHT_GREEN = '92D040';
const GREEN = '00B050'; public const GREEN = '00B050';
const LIGHT_BLUE = '00B0E0'; public const LIGHT_BLUE = '00B0E0';
const BLUE = '0070C0'; public const BLUE = '0070C0';
const DARK_BLUE = '002060'; public const DARK_BLUE = '002060';
const PURPLE = '7030A0'; public const PURPLE = '7030A0';
/** /**
* Returns an RGB color from R, G and B values * Returns an RGB color from R, G and B values
+7 -7
View File
@@ -9,9 +9,9 @@ namespace Box\Spout\Common\Entity\Style;
class Style class Style
{ {
/** Default values */ /** Default values */
const DEFAULT_FONT_SIZE = 11; public const DEFAULT_FONT_SIZE = 11;
const DEFAULT_FONT_COLOR = Color::BLACK; public const DEFAULT_FONT_COLOR = Color::BLACK;
const DEFAULT_FONT_NAME = 'Arial'; public const DEFAULT_FONT_NAME = 'Arial';
/** @var int|null Style ID */ /** @var int|null Style ID */
private $id; private $id;
@@ -66,7 +66,7 @@ class Style
/** @var bool Whether the wrap text property was set */ /** @var bool Whether the wrap text property was set */
private $hasSetWrapText = false; private $hasSetWrapText = false;
/** @var Border */ /** @var Border|null */
private $border; private $border;
/** @var bool Whether border properties should be applied */ /** @var bool Whether border properties should be applied */
@@ -78,7 +78,7 @@ class Style
/** @var bool */ /** @var bool */
private $hasSetBackgroundColor = false; private $hasSetBackgroundColor = false;
/** @var string Format */ /** @var string|null Format */
private $format; private $format;
/** @var bool */ /** @var bool */
@@ -110,7 +110,7 @@ class Style
} }
/** /**
* @return Border * @return Border|null
*/ */
public function getBorder() public function getBorder()
{ {
@@ -467,7 +467,7 @@ class Style
} }
/** /**
* @return string * @return string|null
*/ */
public function getFormat() public function getFormat()
{ {
+6 -6
View File
@@ -9,7 +9,7 @@ namespace Box\Spout\Common\Helper;
class CellTypeHelper class CellTypeHelper
{ {
/** /**
* @param $value * @param mixed|null $value
* @return bool Whether the given value is considered "empty" * @return bool Whether the given value is considered "empty"
*/ */
public static function isEmpty($value) public static function isEmpty($value)
@@ -18,7 +18,7 @@ class CellTypeHelper
} }
/** /**
* @param $value * @param mixed $value
* @return bool Whether the given value is a non empty string * @return bool Whether the given value is a non empty string
*/ */
public static function isNonEmptyString($value) public static function isNonEmptyString($value)
@@ -30,7 +30,7 @@ class CellTypeHelper
* Returns whether the given value is numeric. * Returns whether the given value is numeric.
* A numeric value is from type "integer" or "double" ("float" is not returned by gettype). * A numeric value is from type "integer" or "double" ("float" is not returned by gettype).
* *
* @param $value * @param mixed $value
* @return bool Whether the given value is numeric * @return bool Whether the given value is numeric
*/ */
public static function isNumeric($value) public static function isNumeric($value)
@@ -44,7 +44,7 @@ class CellTypeHelper
* Returns whether the given value is boolean. * Returns whether the given value is boolean.
* "true"/"false" and 0/1 are not booleans. * "true"/"false" and 0/1 are not booleans.
* *
* @param $value * @param mixed $value
* @return bool Whether the given value is boolean * @return bool Whether the given value is boolean
*/ */
public static function isBoolean($value) public static function isBoolean($value)
@@ -55,13 +55,13 @@ class CellTypeHelper
/** /**
* Returns whether the given value is a DateTime or DateInterval object. * Returns whether the given value is a DateTime or DateInterval object.
* *
* @param $value * @param mixed $value
* @return bool Whether the given value is a DateTime or DateInterval object * @return bool Whether the given value is a DateTime or DateInterval object
*/ */
public static function isDateTimeOrDateInterval($value) public static function isDateTimeOrDateInterval($value)
{ {
return ( return (
$value instanceof \DateTime || $value instanceof \DateTimeInterface ||
$value instanceof \DateInterval $value instanceof \DateInterval
); );
} }
+10 -10
View File
@@ -11,18 +11,18 @@ use Box\Spout\Common\Exception\EncodingConversionException;
class EncodingHelper class EncodingHelper
{ {
/** Definition of the encodings that can have a BOM */ /** Definition of the encodings that can have a BOM */
const ENCODING_UTF8 = 'UTF-8'; public const ENCODING_UTF8 = 'UTF-8';
const ENCODING_UTF16_LE = 'UTF-16LE'; public const ENCODING_UTF16_LE = 'UTF-16LE';
const ENCODING_UTF16_BE = 'UTF-16BE'; public const ENCODING_UTF16_BE = 'UTF-16BE';
const ENCODING_UTF32_LE = 'UTF-32LE'; public const ENCODING_UTF32_LE = 'UTF-32LE';
const ENCODING_UTF32_BE = 'UTF-32BE'; public const ENCODING_UTF32_BE = 'UTF-32BE';
/** Definition of the BOMs for the different encodings */ /** Definition of the BOMs for the different encodings */
const BOM_UTF8 = "\xEF\xBB\xBF"; public const BOM_UTF8 = "\xEF\xBB\xBF";
const BOM_UTF16_LE = "\xFF\xFE"; public const BOM_UTF16_LE = "\xFF\xFE";
const BOM_UTF16_BE = "\xFE\xFF"; public const BOM_UTF16_BE = "\xFE\xFF";
const BOM_UTF32_LE = "\xFF\xFE\x00\x00"; public const BOM_UTF32_LE = "\xFF\xFE\x00\x00";
const BOM_UTF32_BE = "\x00\x00\xFE\xFF"; public const BOM_UTF32_BE = "\x00\x00\xFE\xFF";
/** @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;
@@ -82,7 +82,7 @@ class GlobalFunctionsHelper
* @param int|null $length * @param int|null $length
* @param string|null $delimiter * @param string|null $delimiter
* @param string|null $enclosure * @param string|null $enclosure
* @return array * @return array|false
*/ */
public function fgetcsv($handle, $length = null, $delimiter = null, $enclosure = null) public function fgetcsv($handle, $length = null, $delimiter = null, $enclosure = null)
{ {
@@ -103,7 +103,7 @@ class GlobalFunctionsHelper
* @param array $fields * @param array $fields
* @param string|null $delimiter * @param string|null $delimiter
* @param string|null $enclosure * @param string|null $enclosure
* @return int * @return int|false
*/ */
public function fputcsv($handle, array $fields, $delimiter = null, $enclosure = null) public function fputcsv($handle, array $fields, $delimiter = null, $enclosure = null)
{ {
@@ -243,10 +243,10 @@ class GlobalFunctionsHelper
* @see basename() * @see basename()
* *
* @param string $path * @param string $path
* @param string|null $suffix * @param string $suffix
* @return string * @return string
*/ */
public function basename($path, $suffix = null) public function basename($path, $suffix = '')
{ {
return \basename($path, $suffix); return \basename($path, $suffix);
} }
+1 -1
View File
@@ -88,7 +88,7 @@ class StringHelper
* @see https://wiki.php.net/rfc/locale_independent_float_to_string for the changed behavior in PHP8. * @see https://wiki.php.net/rfc/locale_independent_float_to_string for the changed behavior in PHP8.
* *
* @param int|float $numericValue * @param int|float $numericValue
* @return string * @return int|float|string
*/ */
public function formatNumericValue($numericValue) public function formatNumericValue($numericValue)
{ {
@@ -7,7 +7,7 @@ namespace Box\Spout\Common\Manager;
*/ */
abstract class OptionsManagerAbstract implements OptionsManagerInterface abstract class OptionsManagerAbstract implements OptionsManagerInterface
{ {
const PREFIX_OPTION = 'OPTION_'; public const PREFIX_OPTION = 'OPTION_';
/** @var string[] List of all supported option names */ /** @var string[] List of all supported option names */
private $supportedOptions = []; private $supportedOptions = [];
+3 -3
View File
@@ -8,7 +8,7 @@ namespace Box\Spout\Common;
*/ */
abstract class Type abstract class Type
{ {
const CSV = 'csv'; public const CSV = 'csv';
const XLSX = 'xlsx'; public const XLSX = 'xlsx';
const ODS = 'ods'; public const ODS = 'ods';
} }
+27 -1
View File
@@ -3,6 +3,9 @@
namespace Box\Spout\Reader\CSV; namespace Box\Spout\Reader\CSV;
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\InternalEntityFactoryInterface;
use Box\Spout\Reader\Common\Entity\Options; use Box\Spout\Reader\Common\Entity\Options;
use Box\Spout\Reader\CSV\Creator\InternalEntityFactory; use Box\Spout\Reader\CSV\Creator\InternalEntityFactory;
use Box\Spout\Reader\ReaderAbstract; use Box\Spout\Reader\ReaderAbstract;
@@ -22,6 +25,23 @@ class Reader extends ReaderAbstract
/** @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;
/** @var bool Whether the code is running with PHP >= 8.1 */
private $isRunningAtLeastPhp81;
/**
* @param OptionsManagerInterface $optionsManager
* @param GlobalFunctionsHelper $globalFunctionsHelper
* @param InternalEntityFactoryInterface $entityFactory
*/
public function __construct(
OptionsManagerInterface $optionsManager,
GlobalFunctionsHelper $globalFunctionsHelper,
InternalEntityFactoryInterface $entityFactory
) {
parent::__construct($optionsManager, $globalFunctionsHelper, $entityFactory);
$this->isRunningAtLeastPhp81 = \version_compare(PHP_VERSION, '8.1.0') >= 0;
}
/** /**
* 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.
@@ -84,8 +104,11 @@ class Reader extends ReaderAbstract
*/ */
protected function openReader($filePath) protected function openReader($filePath)
{ {
// "auto_detect_line_endings" is deprecated in PHP 8.1
if (!$this->isRunningAtLeastPhp81) {
$this->originalAutoDetectLineEndings = \ini_get('auto_detect_line_endings'); $this->originalAutoDetectLineEndings = \ini_get('auto_detect_line_endings');
\ini_set('auto_detect_line_endings', '1'); \ini_set('auto_detect_line_endings', '1');
}
$this->filePointer = $this->globalFunctionsHelper->fopen($filePath, 'r'); $this->filePointer = $this->globalFunctionsHelper->fopen($filePath, 'r');
if (!$this->filePointer) { if (!$this->filePointer) {
@@ -119,10 +142,13 @@ class Reader extends ReaderAbstract
*/ */
protected function closeReader() protected function closeReader()
{ {
if ($this->filePointer) { if (is_resource($this->filePointer)) {
$this->globalFunctionsHelper->fclose($this->filePointer); $this->globalFunctionsHelper->fclose($this->filePointer);
} }
// "auto_detect_line_endings" is deprecated in PHP 8.1
if (!$this->isRunningAtLeastPhp81) {
\ini_set('auto_detect_line_endings', $this->originalAutoDetectLineEndings); \ini_set('auto_detect_line_endings', $this->originalAutoDetectLineEndings);
} }
} }
}
+10 -10
View File
@@ -19,9 +19,9 @@ class RowIterator implements IteratorInterface
/** /**
* Value passed to fgetcsv. 0 means "unlimited" (slightly slower but accomodates for very long lines). * Value passed to fgetcsv. 0 means "unlimited" (slightly slower but accomodates for very long lines).
*/ */
const MAX_READ_BYTES_PER_LINE = 0; public const MAX_READ_BYTES_PER_LINE = 0;
/** @var resource Pointer to the CSV file to read */ /** @var resource|null Pointer to the CSV file to read */
protected $filePointer; protected $filePointer;
/** @var int Number of read rows */ /** @var int Number of read rows */
@@ -84,7 +84,7 @@ class RowIterator implements IteratorInterface
* *
* @return void * @return void
*/ */
public function rewind() public function rewind() : void
{ {
$this->rewindAndSkipBom(); $this->rewindAndSkipBom();
@@ -114,7 +114,7 @@ class RowIterator implements IteratorInterface
* *
* @return bool * @return bool
*/ */
public function valid() public function valid() : bool
{ {
return ($this->filePointer && !$this->hasReachedEndOfFile); return ($this->filePointer && !$this->hasReachedEndOfFile);
} }
@@ -126,7 +126,7 @@ class RowIterator implements IteratorInterface
* @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 * @return void
*/ */
public function next() public function next() : void
{ {
$this->hasReachedEndOfFile = $this->globalFunctionsHelper->feof($this->filePointer); $this->hasReachedEndOfFile = $this->globalFunctionsHelper->feof($this->filePointer);
@@ -146,8 +146,8 @@ class RowIterator implements IteratorInterface
} while ($this->shouldReadNextRow($rowData)); } while ($this->shouldReadNextRow($rowData));
if ($rowData !== false) { if ($rowData !== false) {
// str_replace will replace NULL values by empty strings // array_map will replace NULL values by empty strings
$rowDataBufferAsArray = \str_replace(null, null, $rowData); $rowDataBufferAsArray = array_map(function ($value) { return (string) $value; }, $rowData);
$this->rowBuffer = $this->entityFactory->createRowFromArray($rowDataBufferAsArray); $this->rowBuffer = $this->entityFactory->createRowFromArray($rowDataBufferAsArray);
$this->numReadRows++; $this->numReadRows++;
} else { } else {
@@ -224,7 +224,7 @@ class RowIterator implements IteratorInterface
* *
* @return Row|null * @return Row|null
*/ */
public function current() public function current() : ?Row
{ {
return $this->rowBuffer; return $this->rowBuffer;
} }
@@ -235,7 +235,7 @@ class RowIterator implements IteratorInterface
* *
* @return int * @return int
*/ */
public function key() public function key() : int
{ {
return $this->numReadRows; return $this->numReadRows;
} }
@@ -245,7 +245,7 @@ class RowIterator implements IteratorInterface
* *
* @return void * @return void
*/ */
public function end() public function end() : void
{ {
// do nothing // do nothing
} }
+8 -8
View File
@@ -10,7 +10,7 @@ use Box\Spout\Reader\IteratorInterface;
*/ */
class SheetIterator implements IteratorInterface class SheetIterator implements IteratorInterface
{ {
/** @var \Box\Spout\Reader\CSV\Sheet The CSV unique "sheet" */ /** @var Sheet The CSV unique "sheet" */
protected $sheet; protected $sheet;
/** @var bool Whether the unique "sheet" has already been read */ /** @var bool Whether the unique "sheet" has already been read */
@@ -30,7 +30,7 @@ class SheetIterator implements IteratorInterface
* *
* @return void * @return void
*/ */
public function rewind() public function rewind() : void
{ {
$this->hasReadUniqueSheet = false; $this->hasReadUniqueSheet = false;
} }
@@ -41,7 +41,7 @@ class SheetIterator implements IteratorInterface
* *
* @return bool * @return bool
*/ */
public function valid() public function valid() : bool
{ {
return (!$this->hasReadUniqueSheet); return (!$this->hasReadUniqueSheet);
} }
@@ -52,7 +52,7 @@ class SheetIterator implements IteratorInterface
* *
* @return void * @return void
*/ */
public function next() public function next() : void
{ {
$this->hasReadUniqueSheet = true; $this->hasReadUniqueSheet = true;
} }
@@ -61,9 +61,9 @@ class SheetIterator implements IteratorInterface
* Return the current element * Return the current element
* @see http://php.net/manual/en/iterator.current.php * @see http://php.net/manual/en/iterator.current.php
* *
* @return \Box\Spout\Reader\CSV\Sheet * @return Sheet
*/ */
public function current() public function current() : Sheet
{ {
return $this->sheet; return $this->sheet;
} }
@@ -74,7 +74,7 @@ class SheetIterator implements IteratorInterface
* *
* @return int * @return int
*/ */
public function key() public function key() : int
{ {
return 1; return 1;
} }
@@ -84,7 +84,7 @@ class SheetIterator implements IteratorInterface
* *
* @return void * @return void
*/ */
public function end() public function end() : void
{ {
// do nothing // do nothing
} }
@@ -35,6 +35,7 @@ class ReaderEntityFactory
return ReaderFactory::createFromType(Type::CSV); return ReaderFactory::createFromType(Type::CSV);
} catch (UnsupportedTypeException $e) { } catch (UnsupportedTypeException $e) {
// should never happen // should never happen
return null;
} }
} }
@@ -49,6 +50,7 @@ class ReaderEntityFactory
return ReaderFactory::createFromType(Type::XLSX); return ReaderFactory::createFromType(Type::XLSX);
} catch (UnsupportedTypeException $e) { } catch (UnsupportedTypeException $e) {
// should never happen // should never happen
return null;
} }
} }
@@ -63,6 +65,7 @@ class ReaderEntityFactory
return ReaderFactory::createFromType(Type::ODS); return ReaderFactory::createFromType(Type::ODS);
} catch (UnsupportedTypeException $e) { } catch (UnsupportedTypeException $e) {
// should never happen // should never happen
return null;
} }
} }
} }
+7 -7
View File
@@ -9,15 +9,15 @@ namespace Box\Spout\Reader\Common\Entity;
abstract class Options abstract class Options
{ {
// Common options // Common options
const SHOULD_FORMAT_DATES = 'shouldFormatDates'; public const SHOULD_FORMAT_DATES = 'shouldFormatDates';
const SHOULD_PRESERVE_EMPTY_ROWS = 'shouldPreserveEmptyRows'; public const SHOULD_PRESERVE_EMPTY_ROWS = 'shouldPreserveEmptyRows';
// CSV specific options // CSV specific options
const FIELD_DELIMITER = 'fieldDelimiter'; public const FIELD_DELIMITER = 'fieldDelimiter';
const FIELD_ENCLOSURE = 'fieldEnclosure'; public const FIELD_ENCLOSURE = 'fieldEnclosure';
const ENCODING = 'encoding'; public const ENCODING = 'encoding';
// XLSX specific options // XLSX specific options
const TEMP_FOLDER = 'tempFolder'; public const TEMP_FOLDER = 'tempFolder';
const SHOULD_USE_1904_DATES = 'shouldUse1904Dates'; public const SHOULD_USE_1904_DATES = 'shouldUse1904Dates';
} }
+6 -6
View File
@@ -11,16 +11,16 @@ use Box\Spout\Reader\Wrapper\XMLReader;
class XMLProcessor class XMLProcessor
{ {
/* Node types */ /* Node types */
const NODE_TYPE_START = XMLReader::ELEMENT; public const NODE_TYPE_START = XMLReader::ELEMENT;
const NODE_TYPE_END = XMLReader::END_ELEMENT; public const NODE_TYPE_END = XMLReader::END_ELEMENT;
/* Keys associated to reflection attributes to invoke a callback */ /* Keys associated to reflection attributes to invoke a callback */
const CALLBACK_REFLECTION_METHOD = 'reflectionMethod'; public const CALLBACK_REFLECTION_METHOD = 'reflectionMethod';
const CALLBACK_REFLECTION_OBJECT = 'reflectionObject'; public const CALLBACK_REFLECTION_OBJECT = 'reflectionObject';
/* Values returned by the callbacks to indicate what the processor should do next */ /* Values returned by the callbacks to indicate what the processor should do next */
const PROCESSING_CONTINUE = 1; public const PROCESSING_CONTINUE = 1;
const PROCESSING_STOP = 2; public 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;
@@ -105,7 +105,7 @@ class InternalEntityFactory implements InternalEntityFactoryInterface
} }
/** /**
* @param $xmlReader * @param XMLReader $xmlReader
* @return XMLProcessor * @return XMLProcessor
*/ */
private function createXMLProcessor($xmlReader) private function createXMLProcessor($xmlReader)
@@ -11,31 +11,31 @@ use Box\Spout\Reader\Exception\InvalidValueException;
class CellValueFormatter class CellValueFormatter
{ {
/** Definition of all possible cell types */ /** Definition of all possible cell types */
const CELL_TYPE_STRING = 'string'; public const CELL_TYPE_STRING = 'string';
const CELL_TYPE_FLOAT = 'float'; public const CELL_TYPE_FLOAT = 'float';
const CELL_TYPE_BOOLEAN = 'boolean'; public const CELL_TYPE_BOOLEAN = 'boolean';
const CELL_TYPE_DATE = 'date'; public const CELL_TYPE_DATE = 'date';
const CELL_TYPE_TIME = 'time'; public const CELL_TYPE_TIME = 'time';
const CELL_TYPE_CURRENCY = 'currency'; public const CELL_TYPE_CURRENCY = 'currency';
const CELL_TYPE_PERCENTAGE = 'percentage'; public const CELL_TYPE_PERCENTAGE = 'percentage';
const CELL_TYPE_VOID = 'void'; public const CELL_TYPE_VOID = 'void';
/** Definition of XML nodes names used to parse data */ /** Definition of XML nodes names used to parse data */
const XML_NODE_P = 'p'; public const XML_NODE_P = 'p';
const XML_NODE_TEXT_A = 'text:a'; public const XML_NODE_TEXT_A = 'text:a';
const XML_NODE_TEXT_SPAN = 'text:span'; public const XML_NODE_TEXT_SPAN = 'text:span';
const XML_NODE_TEXT_S = 'text:s'; public const XML_NODE_TEXT_S = 'text:s';
const XML_NODE_TEXT_TAB = 'text:tab'; public const XML_NODE_TEXT_TAB = 'text:tab';
const XML_NODE_TEXT_LINE_BREAK = 'text:line-break'; public const XML_NODE_TEXT_LINE_BREAK = 'text:line-break';
/** Definition of XML attributes used to parse data */ /** Definition of XML attributes used to parse data */
const XML_ATTRIBUTE_TYPE = 'office:value-type'; public const XML_ATTRIBUTE_TYPE = 'office:value-type';
const XML_ATTRIBUTE_VALUE = 'office:value'; public const XML_ATTRIBUTE_VALUE = 'office:value';
const XML_ATTRIBUTE_BOOLEAN_VALUE = 'office:boolean-value'; public const XML_ATTRIBUTE_BOOLEAN_VALUE = 'office:boolean-value';
const XML_ATTRIBUTE_DATE_VALUE = 'office:date-value'; public const XML_ATTRIBUTE_DATE_VALUE = 'office:date-value';
const XML_ATTRIBUTE_TIME_VALUE = 'office:time-value'; public const XML_ATTRIBUTE_TIME_VALUE = 'office:time-value';
const XML_ATTRIBUTE_CURRENCY = 'office:currency'; public const XML_ATTRIBUTE_CURRENCY = 'office:currency';
const XML_ATTRIBUTE_C = 'text:c'; public const XML_ATTRIBUTE_C = 'text:c';
/** @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;
@@ -64,7 +64,7 @@ class CellValueFormatter
* Returns the (unescaped) correctly marshalled, cell value associated to the given XML node. * Returns the (unescaped) correctly marshalled, cell value associated to the given XML node.
* @see http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#refTable13 * @see http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#refTable13
* *
* @param \DOMNode $node * @param \DOMElement $node
* @throws InvalidValueException If the node value is not valid * @throws InvalidValueException If the node value is not valid
* @return string|int|float|bool|\DateTime|\DateInterval The value associated with the cell, empty string if cell's type is void/undefined * @return string|int|float|bool|\DateTime|\DateInterval The value associated with the cell, empty string if cell's type is void/undefined
*/ */
@@ -96,7 +96,7 @@ class CellValueFormatter
/** /**
* Returns the cell String value. * Returns the cell String value.
* *
* @param \DOMNode $node * @param \DOMElement $node
* @return string The value associated with the cell * @return string The value associated with the cell
*/ */
protected function formatStringCellValue($node) protected function formatStringCellValue($node)
@@ -115,7 +115,7 @@ class CellValueFormatter
} }
/** /**
* @param $pNode * @param \DOMNode $pNode
* @return string * @return string
*/ */
private function extractTextValueFromNode($pNode) private function extractTextValueFromNode($pNode)
@@ -159,7 +159,7 @@ class CellValueFormatter
* *
* @see https://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#__RefHeading__1415200_253892949 * @see https://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#__RefHeading__1415200_253892949
* *
* @param \DOMNode $node The XML node representing a whitespace * @param \DOMElement $node The XML node representing a whitespace
* @return string The corresponding whitespace value * @return string The corresponding whitespace value
*/ */
private function transformWhitespaceNode($node) private function transformWhitespaceNode($node)
@@ -173,7 +173,7 @@ class CellValueFormatter
/** /**
* Returns the cell Numeric value from the given node. * Returns the cell Numeric value from the given node.
* *
* @param \DOMNode $node * @param \DOMElement $node
* @return int|float The value associated with the cell * @return int|float The value associated with the cell
*/ */
protected function formatFloatCellValue($node) protected function formatFloatCellValue($node)
@@ -190,7 +190,7 @@ class CellValueFormatter
/** /**
* Returns the cell Boolean value from the given node. * Returns the cell Boolean value from the given node.
* *
* @param \DOMNode $node * @param \DOMElement $node
* @return bool The value associated with the cell * @return bool The value associated with the cell
*/ */
protected function formatBooleanCellValue($node) protected function formatBooleanCellValue($node)
@@ -203,7 +203,7 @@ class CellValueFormatter
/** /**
* Returns the cell Date value from the given node. * Returns the cell Date value from the given node.
* *
* @param \DOMNode $node * @param \DOMElement $node
* @throws InvalidValueException If the value is not a valid date * @throws InvalidValueException If the value is not a valid date
* @return \DateTime|string The value associated with the cell * @return \DateTime|string The value associated with the cell
*/ */
@@ -234,7 +234,7 @@ class CellValueFormatter
/** /**
* Returns the cell Time value from the given node. * Returns the cell Time value from the given node.
* *
* @param \DOMNode $node * @param \DOMElement $node
* @throws InvalidValueException If the value is not a valid time * @throws InvalidValueException If the value is not a valid time
* @return \DateInterval|string The value associated with the cell * @return \DateInterval|string The value associated with the cell
*/ */
@@ -265,7 +265,7 @@ class CellValueFormatter
/** /**
* Returns the cell Currency value from the given node. * Returns the cell Currency value from the given node.
* *
* @param \DOMNode $node * @param \DOMElement $node
* @return string The value associated with the cell (e.g. "100 USD" or "9.99 EUR") * @return string The value associated with the cell (e.g. "100 USD" or "9.99 EUR")
*/ */
protected function formatCurrencyCellValue($node) protected function formatCurrencyCellValue($node)
@@ -279,7 +279,7 @@ class CellValueFormatter
/** /**
* Returns the cell Percentage value from the given node. * Returns the cell Percentage value from the given node.
* *
* @param \DOMNode $node * @param \DOMElement $node
* @return int|float The value associated with the cell * @return int|float The value associated with the cell
*/ */
protected function formatPercentageCellValue($node) protected function formatPercentageCellValue($node)
@@ -11,12 +11,12 @@ use Box\Spout\Reader\ODS\Creator\InternalEntityFactory;
*/ */
class SettingsHelper class SettingsHelper
{ {
const SETTINGS_XML_FILE_PATH = 'settings.xml'; public const SETTINGS_XML_FILE_PATH = 'settings.xml';
/** Definition of XML nodes name and attribute used to parse settings data */ /** Definition of XML nodes name and attribute used to parse settings data */
const XML_NODE_CONFIG_ITEM = 'config:config-item'; public const XML_NODE_CONFIG_ITEM = 'config:config-item';
const XML_ATTRIBUTE_CONFIG_NAME = 'config:name'; public const XML_ATTRIBUTE_CONFIG_NAME = 'config:name';
const XML_ATTRIBUTE_VALUE_ACTIVE_TABLE = 'ActiveTable'; public const XML_ATTRIBUTE_VALUE_ACTIVE_TABLE = 'ActiveTable';
/** @var InternalEntityFactory Factory to create entities */ /** @var InternalEntityFactory Factory to create entities */
private $entityFactory; private $entityFactory;
+1 -1
View File
@@ -69,7 +69,7 @@ class Reader extends ReaderAbstract
*/ */
protected function closeReader() protected function closeReader()
{ {
if ($this->zip) { if ($this->zip !== null) {
$this->zip->close(); $this->zip->close();
} }
} }
+17 -16
View File
@@ -23,14 +23,14 @@ use Box\Spout\Reader\Wrapper\XMLReader;
class RowIterator implements IteratorInterface class RowIterator implements IteratorInterface
{ {
/** Definition of XML nodes names used to parse data */ /** Definition of XML nodes names used to parse data */
const XML_NODE_TABLE = 'table:table'; public const XML_NODE_TABLE = 'table:table';
const XML_NODE_ROW = 'table:table-row'; public const XML_NODE_ROW = 'table:table-row';
const XML_NODE_CELL = 'table:table-cell'; public const XML_NODE_CELL = 'table:table-cell';
const MAX_COLUMNS_EXCEL = 16384; public const MAX_COLUMNS_EXCEL = 16384;
/** Definition of XML attribute used to parse data */ /** Definition of XML attribute used to parse data */
const XML_ATTRIBUTE_NUM_ROWS_REPEATED = 'table:number-rows-repeated'; public const XML_ATTRIBUTE_NUM_ROWS_REPEATED = 'table:number-rows-repeated';
const XML_ATTRIBUTE_NUM_COLUMNS_REPEATED = 'table:number-columns-repeated'; public const XML_ATTRIBUTE_NUM_COLUMNS_REPEATED = 'table:number-columns-repeated';
/** @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;
@@ -56,7 +56,7 @@ class RowIterator implements IteratorInterface
/** @var Row The currently processed row */ /** @var Row The currently processed row */
protected $currentlyProcessedRow; protected $currentlyProcessedRow;
/** @var Row Buffer used to store the current row, while checking if there are more rows to read */ /** @var Row|null Buffer used to store the current row, while checking if there are more rows to read */
protected $rowBuffer; protected $rowBuffer;
/** @var bool Indicates whether all rows have been read */ /** @var bool Indicates whether all rows have been read */
@@ -68,7 +68,7 @@ class RowIterator implements IteratorInterface
/** @var int Row index to be processed next (one-based) */ /** @var int Row index to be processed next (one-based) */
protected $nextRowIndexToBeProcessed = 1; protected $nextRowIndexToBeProcessed = 1;
/** @var Cell Last processed cell (because when reading cell at column N+1, cell N is processed) */ /** @var Cell|null Last processed cell (because when reading cell at column N+1, cell N is processed) */
protected $lastProcessedCell; protected $lastProcessedCell;
/** @var int Number of times the last processed row should be repeated */ /** @var int Number of times the last processed row should be repeated */
@@ -118,7 +118,7 @@ class RowIterator implements IteratorInterface
* @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 * @return void
*/ */
public function rewind() public function rewind() : void
{ {
// Because sheet and row data is located in the file, we can't rewind both the // Because sheet and row data is located in the file, we can't rewind both the
// sheet iterator and the row iterator, as XML file cannot be read backwards. // sheet iterator and the row iterator, as XML file cannot be read backwards.
@@ -142,7 +142,7 @@ class RowIterator implements IteratorInterface
* *
* @return bool * @return bool
*/ */
public function valid() public function valid() : bool
{ {
return (!$this->hasReachedEndOfFile); return (!$this->hasReachedEndOfFile);
} }
@@ -155,7 +155,7 @@ class RowIterator implements IteratorInterface
* @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 * @return void
*/ */
public function next() public function next() : void
{ {
if ($this->doesNeedDataForNextRowToBeProcessed()) { if ($this->doesNeedDataForNextRowToBeProcessed()) {
$this->readDataForNextRow(); $this->readDataForNextRow();
@@ -225,6 +225,7 @@ class RowIterator implements IteratorInterface
$currentNumColumnsRepeated = $this->getNumColumnsRepeatedForCurrentNode($xmlReader); $currentNumColumnsRepeated = $this->getNumColumnsRepeatedForCurrentNode($xmlReader);
// NOTE: expand() will automatically decode all XML entities of the child nodes // NOTE: expand() will automatically decode all XML entities of the child nodes
/** @var \DOMElement $node */
$node = $xmlReader->expand(); $node = $xmlReader->expand();
$currentCell = $this->getCell($node); $currentCell = $this->getCell($node);
@@ -316,7 +317,7 @@ class RowIterator implements IteratorInterface
/** /**
* Returns the cell with (unescaped) correctly marshalled, cell value associated to the given XML node. * Returns the cell with (unescaped) correctly marshalled, cell value associated to the given XML node.
* *
* @param \DOMNode $node * @param \DOMElement $node
* @return Cell The cell set with the associated with the cell * @return Cell The cell set with the associated with the cell
*/ */
protected function getCell($node) protected function getCell($node)
@@ -339,7 +340,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 Row $currentRow * @param Row $currentRow
* @param Cell $lastReadCell The last read cell * @param Cell|null $lastReadCell The last read cell
* @return bool Whether the row is empty * @return bool Whether the row is empty
*/ */
protected function isEmptyRow($currentRow, $lastReadCell) protected function isEmptyRow($currentRow, $lastReadCell)
@@ -356,7 +357,7 @@ class RowIterator implements IteratorInterface
* *
* @return Row * @return Row
*/ */
public function current() public function current() : Row
{ {
return $this->rowBuffer; return $this->rowBuffer;
} }
@@ -367,7 +368,7 @@ class RowIterator implements IteratorInterface
* *
* @return int * @return int
*/ */
public function key() public function key() : int
{ {
return $this->lastRowIndexProcessed; return $this->lastRowIndexProcessed;
} }
@@ -377,7 +378,7 @@ class RowIterator implements IteratorInterface
* *
* @return void * @return void
*/ */
public function end() public function end() : void
{ {
$this->xmlReader->close(); $this->xmlReader->close();
} }
+11 -9
View File
@@ -15,18 +15,18 @@ use Box\Spout\Reader\Wrapper\XMLReader;
*/ */
class SheetIterator implements IteratorInterface class SheetIterator implements IteratorInterface
{ {
const CONTENT_XML_FILE_PATH = 'content.xml'; public const CONTENT_XML_FILE_PATH = 'content.xml';
const XML_STYLE_NAMESPACE = 'urn:oasis:names:tc:opendocument:xmlns:style:1.0'; public const XML_STYLE_NAMESPACE = 'urn:oasis:names:tc:opendocument:xmlns:style:1.0';
/** Definition of XML nodes name and attribute used to parse sheet data */ /** Definition of XML nodes name and attribute used to parse sheet data */
const XML_NODE_AUTOMATIC_STYLES = 'office:automatic-styles'; public const XML_NODE_AUTOMATIC_STYLES = 'office:automatic-styles';
const XML_NODE_STYLE_TABLE_PROPERTIES = 'table-properties'; public const XML_NODE_STYLE_TABLE_PROPERTIES = 'table-properties';
const XML_NODE_TABLE = 'table:table'; public const XML_NODE_TABLE = 'table:table';
const XML_ATTRIBUTE_STYLE_NAME = 'style:name'; public const XML_ATTRIBUTE_STYLE_NAME = 'style:name';
const XML_ATTRIBUTE_TABLE_NAME = 'table:name'; public const XML_ATTRIBUTE_TABLE_NAME = 'table:name';
const XML_ATTRIBUTE_TABLE_STYLE_NAME = 'table:style-name'; public const XML_ATTRIBUTE_TABLE_STYLE_NAME = 'table:style-name';
const XML_ATTRIBUTE_TABLE_DISPLAY = 'table:display'; public const XML_ATTRIBUTE_TABLE_DISPLAY = 'table:display';
/** @var string Path of the file to be read */ /** @var string Path of the file to be read */
protected $filePath; protected $filePath;
@@ -108,6 +108,7 @@ class SheetIterator implements IteratorInterface
$sheetsVisibility = []; $sheetsVisibility = [];
$this->xmlReader->readUntilNodeFound(self::XML_NODE_AUTOMATIC_STYLES); $this->xmlReader->readUntilNodeFound(self::XML_NODE_AUTOMATIC_STYLES);
/** @var \DOMElement $automaticStylesNode */
$automaticStylesNode = $this->xmlReader->expand(); $automaticStylesNode = $this->xmlReader->expand();
$tableStyleNodes = $automaticStylesNode->getElementsByTagNameNS(self::XML_STYLE_NAMESPACE, self::XML_NODE_STYLE_TABLE_PROPERTIES); $tableStyleNodes = $automaticStylesNode->getElementsByTagNameNS(self::XML_STYLE_NAMESPACE, self::XML_NODE_STYLE_TABLE_PROPERTIES);
@@ -116,6 +117,7 @@ class SheetIterator implements IteratorInterface
foreach ($tableStyleNodes as $tableStyleNode) { foreach ($tableStyleNodes as $tableStyleNode) {
$isSheetVisible = ($tableStyleNode->getAttribute(self::XML_ATTRIBUTE_TABLE_DISPLAY) !== 'false'); $isSheetVisible = ($tableStyleNode->getAttribute(self::XML_ATTRIBUTE_TABLE_DISPLAY) !== 'false');
/** @var \DOMElement $parentStyleNode */
$parentStyleNode = $tableStyleNode->parentNode; $parentStyleNode = $tableStyleNode->parentNode;
$styleName = $parentStyleNode->getAttribute(self::XML_ATTRIBUTE_STYLE_NAME); $styleName = $parentStyleNode->getAttribute(self::XML_ATTRIBUTE_STYLE_NAME);
+2 -2
View File
@@ -53,7 +53,7 @@ abstract class ReaderAbstract implements ReaderInterface
/** /**
* Closes the reader. To be used after reading the file. * Closes the reader. To be used after reading the file.
* *
* @return ReaderAbstract * @return void
*/ */
abstract protected function closeReader(); abstract protected function closeReader();
@@ -233,7 +233,7 @@ abstract class ReaderAbstract implements ReaderInterface
$this->closeReader(); $this->closeReader();
$sheetIterator = $this->getConcreteSheetIterator(); $sheetIterator = $this->getConcreteSheetIterator();
if ($sheetIterator) { if ($sheetIterator !== null) {
$sheetIterator->end(); $sheetIterator->end();
} }
+1 -1
View File
@@ -11,7 +11,7 @@ class XMLReader extends \XMLReader
{ {
use XMLInternalErrorsHelper; use XMLInternalErrorsHelper;
const ZIP_WRAPPER = 'zip://'; public const ZIP_WRAPPER = 'zip://';
/** /**
* Opens the XML Reader to read a file located inside a ZIP file. * Opens the XML Reader to read a file located inside a ZIP file.
@@ -152,7 +152,7 @@ class InternalEntityFactory implements InternalEntityFactoryInterface
} }
/** /**
* @param $xmlReader * @param XMLReader $xmlReader
* @return XMLProcessor * @return XMLProcessor
*/ */
public function createXMLProcessor($xmlReader) public function createXMLProcessor($xmlReader)
@@ -21,7 +21,7 @@ class ManagerFactory
/** @var CachingStrategyFactory */ /** @var CachingStrategyFactory */
private $cachingStrategyFactory; private $cachingStrategyFactory;
/** @var WorkbookRelationshipsManager */ /** @var WorkbookRelationshipsManager|null */
private $cachedWorkbookRelationshipsManager; private $cachedWorkbookRelationshipsManager;
/** /**
@@ -13,24 +13,24 @@ use Box\Spout\Reader\XLSX\Manager\StyleManager;
class CellValueFormatter class CellValueFormatter
{ {
/** Definition of all possible cell types */ /** Definition of all possible cell types */
const CELL_TYPE_INLINE_STRING = 'inlineStr'; public const CELL_TYPE_INLINE_STRING = 'inlineStr';
const CELL_TYPE_STR = 'str'; public const CELL_TYPE_STR = 'str';
const CELL_TYPE_SHARED_STRING = 's'; public const CELL_TYPE_SHARED_STRING = 's';
const CELL_TYPE_BOOLEAN = 'b'; public const CELL_TYPE_BOOLEAN = 'b';
const CELL_TYPE_NUMERIC = 'n'; public const CELL_TYPE_NUMERIC = 'n';
const CELL_TYPE_DATE = 'd'; public const CELL_TYPE_DATE = 'd';
const CELL_TYPE_ERROR = 'e'; public const CELL_TYPE_ERROR = 'e';
/** Definition of XML nodes names used to parse data */ /** Definition of XML nodes names used to parse data */
const XML_NODE_VALUE = 'v'; public const XML_NODE_VALUE = 'v';
const XML_NODE_INLINE_STRING_VALUE = 't'; public const XML_NODE_INLINE_STRING_VALUE = 't';
/** Definition of XML attributes used to parse data */ /** Definition of XML attributes used to parse data */
const XML_ATTRIBUTE_TYPE = 't'; public const XML_ATTRIBUTE_TYPE = 't';
const XML_ATTRIBUTE_STYLE_ID = 's'; public const XML_ATTRIBUTE_STYLE_ID = 's';
/** Constants used for date formatting */ /** Constants used for date formatting */
const NUM_SECONDS_IN_ONE_DAY = 86400; public const NUM_SECONDS_IN_ONE_DAY = 86400;
/** @var SharedStringsManager Manages shared strings */ /** @var SharedStringsManager Manages shared strings */
protected $sharedStringsManager; protected $sharedStringsManager;
@@ -66,7 +66,7 @@ class CellValueFormatter
/** /**
* Returns the (unescaped) correctly marshalled, cell value associated to the given XML node. * Returns the (unescaped) correctly marshalled, cell value associated to the given XML node.
* *
* @param \DOMNode $node * @param \DOMElement $node
* @throws InvalidValueException If the value is not valid * @throws InvalidValueException If the value is not valid
* @return string|int|float|bool|\DateTime The value associated with the cell * @return string|int|float|bool|\DateTime The value associated with the cell
*/ */
@@ -102,7 +102,7 @@ class CellValueFormatter
/** /**
* Returns the cell's string value from a node's nested value node * Returns the cell's string value from a node's nested value node
* *
* @param \DOMNode $node * @param \DOMElement $node
* @return string The value associated with the cell * @return string The value associated with the cell
*/ */
protected function getVNodeValue($node) protected function getVNodeValue($node)
@@ -117,7 +117,7 @@ class CellValueFormatter
/** /**
* Returns the cell String value where string is inline. * Returns the cell String value where string is inline.
* *
* @param \DOMNode $node * @param \DOMElement $node
* @return string The value associated with the cell * @return string The value associated with the cell
*/ */
protected function formatInlineStringCellValue($node) protected function formatInlineStringCellValue($node)
@@ -8,9 +8,9 @@ namespace Box\Spout\Reader\XLSX\Helper;
*/ */
class DateFormatHelper class DateFormatHelper
{ {
const KEY_GENERAL = 'general'; public const KEY_GENERAL = 'general';
const KEY_HOUR_12 = '12h'; public const KEY_HOUR_12 = '12h';
const KEY_HOUR_24 = '24h'; public const KEY_HOUR_24 = '24h';
/** /**
* This map is used to replace Excel format characters by their PHP equivalent. * This map is used to replace Excel format characters by their PHP equivalent.
@@ -37,7 +37,7 @@ class CachingStrategyFactory
* This means that in order to store one shared string in memory, the memory amount needed is: * This means that in order to store one shared string in memory, the memory amount needed is:
* => 20 * 600 ≈ 12KB * => 20 * 600 ≈ 12KB
*/ */
const AMOUNT_MEMORY_NEEDED_PER_STRING_IN_KB = 12; public const AMOUNT_MEMORY_NEEDED_PER_STRING_IN_KB = 12;
/** /**
* To avoid running out of memory when extracting a huge number of shared strings, they can be saved to temporary files * To avoid running out of memory when extracting a huge number of shared strings, they can be saved to temporary files
@@ -48,7 +48,7 @@ class CachingStrategyFactory
* best when the indexes of the shared strings are sorted in the sheet data. * best when the indexes of the shared strings are sorted in the sheet data.
* 10,000 was chosen because it creates small files that are fast to be loaded in memory. * 10,000 was chosen because it creates small files that are fast to be loaded in memory.
*/ */
const MAX_NUM_STRINGS_PER_TEMP_FILE = 10000; public const MAX_NUM_STRINGS_PER_TEMP_FILE = 10000;
/** /**
* Returns the best caching strategy, given the number of unique shared strings * Returns the best caching strategy, given the number of unique shared strings
@@ -84,7 +84,7 @@ class CachingStrategyFactory
$memoryAvailable = $this->getMemoryLimitInKB(); $memoryAvailable = $this->getMemoryLimitInKB();
if ($memoryAvailable === -1) { if ((int) $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
$isInMemoryStrategyUsageSafe = ($sharedStringsUniqueCount < self::MAX_NUM_STRINGS_PER_TEMP_FILE); $isInMemoryStrategyUsageSafe = ($sharedStringsUniqueCount < self::MAX_NUM_STRINGS_PER_TEMP_FILE);
} else { } else {
@@ -15,7 +15,7 @@ use Box\Spout\Reader\XLSX\Creator\HelperFactory;
class FileBasedStrategy implements CachingStrategyInterface class FileBasedStrategy implements CachingStrategyInterface
{ {
/** Value to use to escape the line feed character ("\n") */ /** Value to use to escape the line feed character ("\n") */
const ESCAPED_LINE_FEED_CHARACTER = '_x000A_'; public const ESCAPED_LINE_FEED_CHARACTER = '_x000A_';
/** @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;
@@ -32,7 +32,7 @@ class FileBasedStrategy implements CachingStrategyInterface
*/ */
protected $maxNumStringsPerTempFile; protected $maxNumStringsPerTempFile;
/** @var resource Pointer to the last temp file a shared string was written to */ /** @var resource|null Pointer to the last temp file a shared string was written to */
protected $tempFilePointer; protected $tempFilePointer;
/** /**
@@ -17,16 +17,16 @@ use Box\Spout\Reader\XLSX\Manager\SharedStringsCaching\CachingStrategyInterface;
class SharedStringsManager class SharedStringsManager
{ {
/** Definition of XML nodes names used to parse data */ /** Definition of XML nodes names used to parse data */
const XML_NODE_SST = 'sst'; public const XML_NODE_SST = 'sst';
const XML_NODE_SI = 'si'; public const XML_NODE_SI = 'si';
const XML_NODE_R = 'r'; public const XML_NODE_R = 'r';
const XML_NODE_T = 't'; public const XML_NODE_T = 't';
/** Definition of XML attributes used to parse data */ /** Definition of XML attributes used to parse data */
const XML_ATTRIBUTE_COUNT = 'count'; public const XML_ATTRIBUTE_COUNT = 'count';
const XML_ATTRIBUTE_UNIQUE_COUNT = 'uniqueCount'; public const XML_ATTRIBUTE_UNIQUE_COUNT = 'uniqueCount';
const XML_ATTRIBUTE_XML_SPACE = 'xml:space'; public const XML_ATTRIBUTE_XML_SPACE = 'xml:space';
const XML_ATTRIBUTE_VALUE_PRESERVE = 'preserve'; public const XML_ATTRIBUTE_VALUE_PRESERVE = 'preserve';
/** @var string Path of the XLSX file being read */ /** @var string Path of the XLSX file being read */
protected $filePath; protected $filePath;
@@ -179,6 +179,7 @@ class SharedStringsManager
$sharedStringValue = ''; $sharedStringValue = '';
// NOTE: expand() will automatically decode all XML entities of the child nodes // NOTE: expand() will automatically decode all XML entities of the child nodes
/** @var \DOMElement $siNode */
$siNode = $xmlReader->expand(); $siNode = $xmlReader->expand();
$textNodes = $siNode->getElementsByTagName(self::XML_NODE_T); $textNodes = $siNode->getElementsByTagName(self::XML_NODE_T);
@@ -241,7 +242,7 @@ class SharedStringsManager
*/ */
public function cleanup() public function cleanup()
{ {
if ($this->cachingStrategy) { if ($this->cachingStrategy !== null) {
$this->cachingStrategy->clearCache(); $this->cachingStrategy->clearCache();
} }
} }
+15 -15
View File
@@ -14,27 +14,27 @@ use Box\Spout\Reader\XLSX\Sheet;
class SheetManager 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'; public const WORKBOOK_XML_RELS_FILE_PATH = 'xl/_rels/workbook.xml.rels';
const WORKBOOK_XML_FILE_PATH = 'xl/workbook.xml'; public const WORKBOOK_XML_FILE_PATH = 'xl/workbook.xml';
/** Definition of XML node names used to parse data */ /** Definition of XML node names used to parse data */
const XML_NODE_WORKBOOK_PROPERTIES = 'workbookPr'; public const XML_NODE_WORKBOOK_PROPERTIES = 'workbookPr';
const XML_NODE_WORKBOOK_VIEW = 'workbookView'; public const XML_NODE_WORKBOOK_VIEW = 'workbookView';
const XML_NODE_SHEET = 'sheet'; public const XML_NODE_SHEET = 'sheet';
const XML_NODE_SHEETS = 'sheets'; public const XML_NODE_SHEETS = 'sheets';
const XML_NODE_RELATIONSHIP = 'Relationship'; public const XML_NODE_RELATIONSHIP = 'Relationship';
/** Definition of XML attributes used to parse data */ /** Definition of XML attributes used to parse data */
const XML_ATTRIBUTE_DATE_1904 = 'date1904'; public const XML_ATTRIBUTE_DATE_1904 = 'date1904';
const XML_ATTRIBUTE_ACTIVE_TAB = 'activeTab'; public const XML_ATTRIBUTE_ACTIVE_TAB = 'activeTab';
const XML_ATTRIBUTE_R_ID = 'r:id'; public const XML_ATTRIBUTE_R_ID = 'r:id';
const XML_ATTRIBUTE_NAME = 'name'; public const XML_ATTRIBUTE_NAME = 'name';
const XML_ATTRIBUTE_STATE = 'state'; public const XML_ATTRIBUTE_STATE = 'state';
const XML_ATTRIBUTE_ID = 'Id'; public const XML_ATTRIBUTE_ID = 'Id';
const XML_ATTRIBUTE_TARGET = 'Target'; public const XML_ATTRIBUTE_TARGET = 'Target';
/** State value to represent a hidden sheet */ /** State value to represent a hidden sheet */
const SHEET_STATE_HIDDEN = 'hidden'; public const SHEET_STATE_HIDDEN = 'hidden';
/** @var string Path of the XLSX file being read */ /** @var string Path of the XLSX file being read */
protected $filePath; protected $filePath;
+11 -11
View File
@@ -11,20 +11,20 @@ use Box\Spout\Reader\XLSX\Creator\InternalEntityFactory;
class StyleManager class StyleManager
{ {
/** Nodes used to find relevant information in the styles XML file */ /** Nodes used to find relevant information in the styles XML file */
const XML_NODE_NUM_FMTS = 'numFmts'; public const XML_NODE_NUM_FMTS = 'numFmts';
const XML_NODE_NUM_FMT = 'numFmt'; public const XML_NODE_NUM_FMT = 'numFmt';
const XML_NODE_CELL_XFS = 'cellXfs'; public const XML_NODE_CELL_XFS = 'cellXfs';
const XML_NODE_XF = 'xf'; public const XML_NODE_XF = 'xf';
/** Attributes used to find relevant information in the styles XML file */ /** Attributes used to find relevant information in the styles XML file */
const XML_ATTRIBUTE_NUM_FMT_ID = 'numFmtId'; public const XML_ATTRIBUTE_NUM_FMT_ID = 'numFmtId';
const XML_ATTRIBUTE_FORMAT_CODE = 'formatCode'; public const XML_ATTRIBUTE_FORMAT_CODE = 'formatCode';
const XML_ATTRIBUTE_APPLY_NUMBER_FORMAT = 'applyNumberFormat'; public const XML_ATTRIBUTE_APPLY_NUMBER_FORMAT = 'applyNumberFormat';
/** By convention, default style ID is 0 */ /** By convention, default style ID is 0 */
const DEFAULT_STYLE_ID = 0; public const DEFAULT_STYLE_ID = 0;
const NUMBER_FORMAT_GENERAL = 'General'; public const NUMBER_FORMAT_GENERAL = 'General';
/** /**
* @see https://msdn.microsoft.com/en-us/library/ff529597(v=office.12).aspx * @see https://msdn.microsoft.com/en-us/library/ff529597(v=office.12).aspx
@@ -60,10 +60,10 @@ class StyleManager
/** @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;
/** @var array Array containing a mapping NUM_FMT_ID => FORMAT_CODE */ /** @var array|null Array containing a mapping NUM_FMT_ID => FORMAT_CODE */
protected $customNumberFormats; protected $customNumberFormats;
/** @var array Array containing a mapping STYLE_ID => [STYLE_ATTRIBUTES] */ /** @var array|null Array containing a mapping STYLE_ID => [STYLE_ATTRIBUTES] */
protected $stylesAttributes; protected $stylesAttributes;
/** @var array Cache containing a mapping NUM_FMT_ID => IS_DATE_FORMAT. Used to avoid lots of recalculations */ /** @var array Cache containing a mapping NUM_FMT_ID => IS_DATE_FORMAT. Used to avoid lots of recalculations */
@@ -12,21 +12,21 @@ use Box\Spout\Reader\XLSX\Creator\InternalEntityFactory;
*/ */
class WorkbookRelationshipsManager class WorkbookRelationshipsManager
{ {
const BASE_PATH = 'xl/'; public const BASE_PATH = 'xl/';
/** Path of workbook relationships XML file inside the XLSX file */ /** Path of workbook relationships XML file inside the XLSX file */
const WORKBOOK_RELS_XML_FILE_PATH = 'xl/_rels/workbook.xml.rels'; public const WORKBOOK_RELS_XML_FILE_PATH = 'xl/_rels/workbook.xml.rels';
/** Relationships types - For Transitional and Strict OOXML */ /** Relationships types - For Transitional and Strict OOXML */
const RELATIONSHIP_TYPE_SHARED_STRINGS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings'; public const RELATIONSHIP_TYPE_SHARED_STRINGS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings';
const RELATIONSHIP_TYPE_STYLES = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles'; public const RELATIONSHIP_TYPE_STYLES = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles';
const RELATIONSHIP_TYPE_SHARED_STRINGS_STRICT = 'http://purl.oclc.org/ooxml/officeDocument/relationships/sharedStrings'; public const RELATIONSHIP_TYPE_SHARED_STRINGS_STRICT = 'http://purl.oclc.org/ooxml/officeDocument/relationships/sharedStrings';
const RELATIONSHIP_TYPE_STYLES_STRICT = 'http://purl.oclc.org/ooxml/officeDocument/relationships/styles'; public const RELATIONSHIP_TYPE_STYLES_STRICT = 'http://purl.oclc.org/ooxml/officeDocument/relationships/styles';
/** Nodes and attributes used to find relevant information in the workbook relationships XML file */ /** Nodes and attributes used to find relevant information in the workbook relationships XML file */
const XML_NODE_RELATIONSHIP = 'Relationship'; public const XML_NODE_RELATIONSHIP = 'Relationship';
const XML_ATTRIBUTE_TYPE = 'Type'; public const XML_ATTRIBUTE_TYPE = 'Type';
const XML_ATTRIBUTE_TARGET = 'Target'; public const XML_ATTRIBUTE_TARGET = 'Target';
/** @var string Path of the XLSX file being read */ /** @var string Path of the XLSX file being read */
private $filePath; private $filePath;
@@ -34,7 +34,7 @@ class WorkbookRelationshipsManager
/** @var InternalEntityFactory Factory to create entities */ /** @var InternalEntityFactory Factory to create entities */
private $entityFactory; private $entityFactory;
/** @var array Cache of the already read workbook relationships: [TYPE] => [FILE_NAME] */ /** @var array|null Cache of the already read workbook relationships: [TYPE] => [FILE_NAME] */
private $cachedWorkbookRelationships; private $cachedWorkbookRelationships;
/** /**
+2 -2
View File
@@ -119,11 +119,11 @@ class Reader extends ReaderAbstract
*/ */
protected function closeReader() protected function closeReader()
{ {
if ($this->zip) { if ($this->zip !== null) {
$this->zip->close(); $this->zip->close();
} }
if ($this->sharedStringsManager) { if ($this->sharedStringsManager !== null) {
$this->sharedStringsManager->cleanup(); $this->sharedStringsManager->cleanup();
} }
} }
+16 -15
View File
@@ -21,16 +21,16 @@ use Box\Spout\Reader\XLSX\Helper\CellValueFormatter;
class RowIterator implements IteratorInterface class RowIterator implements IteratorInterface
{ {
/** Definition of XML nodes names used to parse data */ /** Definition of XML nodes names used to parse data */
const XML_NODE_DIMENSION = 'dimension'; public const XML_NODE_DIMENSION = 'dimension';
const XML_NODE_WORKSHEET = 'worksheet'; public const XML_NODE_WORKSHEET = 'worksheet';
const XML_NODE_ROW = 'row'; public const XML_NODE_ROW = 'row';
const XML_NODE_CELL = 'c'; public const XML_NODE_CELL = 'c';
/** Definition of XML attributes used to parse data */ /** Definition of XML attributes used to parse data */
const XML_ATTRIBUTE_REF = 'ref'; public const XML_ATTRIBUTE_REF = 'ref';
const XML_ATTRIBUTE_SPANS = 'spans'; public const XML_ATTRIBUTE_SPANS = 'spans';
const XML_ATTRIBUTE_ROW_INDEX = 'r'; public const XML_ATTRIBUTE_ROW_INDEX = 'r';
const XML_ATTRIBUTE_CELL_INDEX = 'r'; public const XML_ATTRIBUTE_CELL_INDEX = 'r';
/** @var string Path of the XLSX file being read */ /** @var string Path of the XLSX file being read */
protected $filePath; protected $filePath;
@@ -139,7 +139,7 @@ class RowIterator implements IteratorInterface
* @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 * @return void
*/ */
public function rewind() public function rewind() : void
{ {
$this->xmlReader->close(); $this->xmlReader->close();
@@ -163,7 +163,7 @@ class RowIterator implements IteratorInterface
* *
* @return bool * @return bool
*/ */
public function valid() public function valid() : bool
{ {
return (!$this->hasReachedEndOfFile); return (!$this->hasReachedEndOfFile);
} }
@@ -176,7 +176,7 @@ class RowIterator implements IteratorInterface
* @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 * @return void
*/ */
public function next() public function next() : void
{ {
$this->nextRowIndexToBeProcessed++; $this->nextRowIndexToBeProcessed++;
@@ -276,6 +276,7 @@ class RowIterator implements IteratorInterface
$currentColumnIndex = $this->getColumnIndex($xmlReader); $currentColumnIndex = $this->getColumnIndex($xmlReader);
// NOTE: expand() will automatically decode all XML entities of the child nodes // NOTE: expand() will automatically decode all XML entities of the child nodes
/** @var \DOMElement $node */
$node = $xmlReader->expand(); $node = $xmlReader->expand();
$cell = $this->getCell($node); $cell = $this->getCell($node);
@@ -352,7 +353,7 @@ class RowIterator implements IteratorInterface
/** /**
* Returns the cell with (unescaped) correctly marshalled, cell value associated to the given XML node. * Returns the cell with (unescaped) correctly marshalled, cell value associated to the given XML node.
* *
* @param \DOMNode $node * @param \DOMElement $node
* @return Cell The cell set with the associated with the cell * @return Cell The cell set with the associated with the cell
*/ */
protected function getCell($node) protected function getCell($node)
@@ -374,7 +375,7 @@ class RowIterator implements IteratorInterface
* *
* @return Row|null * @return Row|null
*/ */
public function current() public function current() : ?Row
{ {
$rowToBeProcessed = $this->rowBuffer; $rowToBeProcessed = $this->rowBuffer;
@@ -399,7 +400,7 @@ class RowIterator implements IteratorInterface
* *
* @return int * @return int
*/ */
public function key() public function key() : int
{ {
// TODO: This should return $this->nextRowIndexToBeProcessed // TODO: This should return $this->nextRowIndexToBeProcessed
// but to avoid a breaking change, the return value for // but to avoid a breaking change, the return value for
@@ -414,7 +415,7 @@ class RowIterator implements IteratorInterface
* *
* @return void * @return void
*/ */
public function end() public function end() : void
{ {
$this->xmlReader->close(); $this->xmlReader->close();
} }
+1 -1
View File
@@ -15,7 +15,7 @@ use Box\Spout\Writer\WriterAbstract;
class Writer extends WriterAbstract class Writer extends WriterAbstract
{ {
/** Number of rows to write before flushing */ /** Number of rows to write before flushing */
const FLUSH_THRESHOLD = 500; public const FLUSH_THRESHOLD = 500;
/** @var string Content-Type value for the header */ /** @var string Content-Type value for the header */
protected static $headerContentType = 'text/csv; charset=UTF-8'; protected static $headerContentType = 'text/csv; charset=UTF-8';
@@ -50,6 +50,7 @@ class WriterEntityFactory
return WriterFactory::createFromType(Type::CSV); return WriterFactory::createFromType(Type::CSV);
} catch (UnsupportedTypeException $e) { } catch (UnsupportedTypeException $e) {
// should never happen // should never happen
return null;
} }
} }
@@ -64,6 +65,7 @@ class WriterEntityFactory
return WriterFactory::createFromType(Type::XLSX); return WriterFactory::createFromType(Type::XLSX);
} catch (UnsupportedTypeException $e) { } catch (UnsupportedTypeException $e) {
// should never happen // should never happen
return null;
} }
} }
@@ -78,6 +80,7 @@ class WriterEntityFactory
return WriterFactory::createFromType(Type::ODS); return WriterFactory::createFromType(Type::ODS);
} catch (UnsupportedTypeException $e) { } catch (UnsupportedTypeException $e) {
// should never happen // should never happen
return null;
} }
} }
+7 -7
View File
@@ -9,15 +9,15 @@ namespace Box\Spout\Writer\Common\Entity;
abstract class Options abstract class Options
{ {
// CSV specific options // CSV specific options
const FIELD_DELIMITER = 'fieldDelimiter'; public const FIELD_DELIMITER = 'fieldDelimiter';
const FIELD_ENCLOSURE = 'fieldEnclosure'; public const FIELD_ENCLOSURE = 'fieldEnclosure';
const SHOULD_ADD_BOM = 'shouldAddBOM'; public const SHOULD_ADD_BOM = 'shouldAddBOM';
// Multisheets options // Multisheets options
const TEMP_FOLDER = 'tempFolder'; public const TEMP_FOLDER = 'tempFolder';
const DEFAULT_ROW_STYLE = 'defaultRowStyle'; public const DEFAULT_ROW_STYLE = 'defaultRowStyle';
const SHOULD_CREATE_NEW_SHEETS_AUTOMATICALLY = 'shouldCreateNewSheetsAutomatically'; public const SHOULD_CREATE_NEW_SHEETS_AUTOMATICALLY = 'shouldCreateNewSheetsAutomatically';
// XLSX specific options // XLSX specific options
const SHOULD_USE_INLINE_STRINGS = 'shouldUseInlineStrings'; public const SHOULD_USE_INLINE_STRINGS = 'shouldUseInlineStrings';
} }
+1 -1
View File
@@ -10,7 +10,7 @@ use Box\Spout\Writer\Common\Manager\SheetManager;
*/ */
class Sheet class Sheet
{ {
const DEFAULT_SHEET_NAME_PREFIX = 'Sheet'; public const DEFAULT_SHEET_NAME_PREFIX = 'Sheet';
/** @var int Index of the sheet, based on order in the workbook (zero-based) */ /** @var int Index of the sheet, based on order in the workbook (zero-based) */
private $index; private $index;
+1 -1
View File
@@ -11,7 +11,7 @@ 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|null 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 */
+3 -3
View File
@@ -10,11 +10,11 @@ use Box\Spout\Writer\Common\Creator\InternalEntityFactory;
*/ */
class ZipHelper class ZipHelper
{ {
const ZIP_EXTENSION = '.zip'; public const ZIP_EXTENSION = '.zip';
/** Controls what to do when trying to add an existing file */ /** Controls what to do when trying to add an existing file */
const EXISTING_FILES_SKIP = 'skip'; public const EXISTING_FILES_SKIP = 'skip';
const EXISTING_FILES_OVERWRITE = 'overwrite'; public const EXISTING_FILES_OVERWRITE = 'overwrite';
/** @var InternalEntityFactory Factory to create entities */ /** @var InternalEntityFactory Factory to create entities */
private $entityFactory; private $entityFactory;
@@ -13,7 +13,7 @@ use Box\Spout\Writer\Exception\InvalidSheetNameException;
class SheetManager class SheetManager
{ {
/** Sheet name should not exceed 31 characters */ /** Sheet name should not exceed 31 characters */
const MAX_LENGTH_SHEET_NAME = 31; public const MAX_LENGTH_SHEET_NAME = 31;
/** @var array Invalid characters that cannot be contained in the sheet name */ /** @var array Invalid characters that cannot be contained in the sheet name */
private static $INVALID_CHARACTERS_IN_SHEET_NAME = ['\\', '/', '?', '*', ':', '[', ']']; private static $INVALID_CHARACTERS_IN_SHEET_NAME = ['\\', '/', '?', '*', ':', '[', ']'];
@@ -88,10 +88,10 @@ class StyleMerger
if (!$style->hasSetCellAlignment() && $baseStyle->shouldApplyCellAlignment()) { if (!$style->hasSetCellAlignment() && $baseStyle->shouldApplyCellAlignment()) {
$styleToUpdate->setCellAlignment($baseStyle->getCellAlignment()); $styleToUpdate->setCellAlignment($baseStyle->getCellAlignment());
} }
if (!$style->getBorder() && $baseStyle->shouldApplyBorder()) { if ($style->getBorder() === null && $baseStyle->shouldApplyBorder()) {
$styleToUpdate->setBorder($baseStyle->getBorder()); $styleToUpdate->setBorder($baseStyle->getBorder());
} }
if (!$style->getFormat() && $baseStyle->shouldApplyFormat()) { if ($style->getFormat() === null && $baseStyle->shouldApplyFormat()) {
$styleToUpdate->setFormat($baseStyle->getFormat()); $styleToUpdate->setFormat($baseStyle->getFormat());
} }
if (!$style->shouldApplyBackgroundColor() && $baseStyle->shouldApplyBackgroundColor()) { if (!$style->shouldApplyBackgroundColor() && $baseStyle->shouldApplyBackgroundColor()) {
@@ -23,7 +23,7 @@ use Box\Spout\Writer\Exception\WriterException;
*/ */
abstract class WorkbookManagerAbstract implements WorkbookManagerInterface abstract class WorkbookManagerAbstract implements WorkbookManagerInterface
{ {
/** @var Workbook The workbook to manage */ /** @var Workbook|null The workbook to manage */
protected $workbook; protected $workbook;
/** @var OptionsManagerInterface */ /** @var OptionsManagerInterface */
@@ -92,7 +92,7 @@ abstract class WorkbookManagerAbstract implements WorkbookManagerInterface
abstract protected function getWorksheetFilePath(Sheet $sheet); abstract protected function getWorksheetFilePath(Sheet $sheet);
/** /**
* @return Workbook * @return Workbook|null
*/ */
public function getWorkbook() public function getWorkbook()
{ {
@@ -17,7 +17,7 @@ use Box\Spout\Writer\Exception\WriterException;
interface WorkbookManagerInterface interface WorkbookManagerInterface
{ {
/** /**
* @return Workbook * @return Workbook|null
*/ */
public function getWorkbook(); public function getWorkbook();
@@ -30,7 +30,7 @@ class HelperFactory extends \Box\Spout\Common\Creator\HelperFactory
} }
/** /**
* @param $entityFactory * @param InternalEntityFactory $entityFactory
* @return ZipHelper * @return ZipHelper
*/ */
private function createZipHelper($entityFactory) private function createZipHelper($entityFactory)
@@ -15,17 +15,17 @@ use Box\Spout\Writer\ODS\Manager\WorksheetManager;
*/ */
class FileSystemHelper extends \Box\Spout\Common\Helper\FileSystemHelper implements FileSystemWithRootFolderHelperInterface class FileSystemHelper extends \Box\Spout\Common\Helper\FileSystemHelper implements FileSystemWithRootFolderHelperInterface
{ {
const APP_NAME = 'Spout'; public const APP_NAME = 'Spout';
const MIMETYPE = 'application/vnd.oasis.opendocument.spreadsheet'; public const MIMETYPE = 'application/vnd.oasis.opendocument.spreadsheet';
const META_INF_FOLDER_NAME = 'META-INF'; public const META_INF_FOLDER_NAME = 'META-INF';
const SHEETS_CONTENT_TEMP_FOLDER_NAME = 'worksheets-temp'; public const SHEETS_CONTENT_TEMP_FOLDER_NAME = 'worksheets-temp';
const MANIFEST_XML_FILE_NAME = 'manifest.xml'; public const MANIFEST_XML_FILE_NAME = 'manifest.xml';
const CONTENT_XML_FILE_NAME = 'content.xml'; public const CONTENT_XML_FILE_NAME = 'content.xml';
const META_XML_FILE_NAME = 'meta.xml'; public const META_XML_FILE_NAME = 'meta.xml';
const MIMETYPE_FILE_NAME = 'mimetype'; public const MIMETYPE_FILE_NAME = 'mimetype';
const STYLES_XML_FILE_NAME = 'styles.xml'; public const STYLES_XML_FILE_NAME = 'styles.xml';
/** @var ZipHelper Helper to perform tasks with Zip archive */ /** @var ZipHelper Helper to perform tasks with Zip archive */
private $zipHelper; private $zipHelper;
@@ -86,7 +86,7 @@ class WorksheetManager implements WorksheetManagerInterface
* Returns the table XML root node as string. * Returns the table XML root node as string.
* *
* @param Worksheet $worksheet * @param Worksheet $worksheet
* @return string <table> node as string * @return string "<table>" node as string
*/ */
public function getTableElementStartAsString(Worksheet $worksheet) public function getTableElementStartAsString(Worksheet $worksheet)
{ {
+3 -3
View File
@@ -140,8 +140,8 @@ abstract class WriterAbstract implements WriterInterface
$this->globalFunctionsHelper->header('Content-Type: ' . static::$headerContentType); $this->globalFunctionsHelper->header('Content-Type: ' . static::$headerContentType);
$this->globalFunctionsHelper->header( $this->globalFunctionsHelper->header(
'Content-Disposition: attachment; ' . 'Content-Disposition: attachment; ' .
'filename="' . rawurldecode($this->outputFilePath) . '"; ' . 'filename="' . rawurlencode($this->outputFilePath) . '"; ' .
'filename*=UTF-8\'\'' . rawurldecode($this->outputFilePath) 'filename*=UTF-8\'\'' . rawurlencode($this->outputFilePath)
); );
/* /*
@@ -169,7 +169,7 @@ abstract class WriterAbstract implements WriterInterface
*/ */
protected function throwIfFilePointerIsNotAvailable() protected function throwIfFilePointerIsNotAvailable()
{ {
if (!$this->filePointer) { if (!is_resource($this->filePointer)) {
throw new IOException('File pointer has not be opened'); throw new IOException('File pointer has not be opened');
} }
} }
@@ -9,7 +9,6 @@ use Box\Spout\Common\Manager\OptionsManagerInterface;
use Box\Spout\Writer\Common\Creator\ManagerFactoryInterface; use Box\Spout\Writer\Common\Creator\ManagerFactoryInterface;
use Box\Spout\Writer\Common\Entity\Options; use Box\Spout\Writer\Common\Entity\Options;
use Box\Spout\Writer\Common\Entity\Sheet; use Box\Spout\Writer\Common\Entity\Sheet;
use Box\Spout\Writer\Common\Entity\Worksheet;
use Box\Spout\Writer\Common\Manager\WorkbookManagerInterface; use Box\Spout\Writer\Common\Manager\WorkbookManagerInterface;
use Box\Spout\Writer\Exception\SheetNotFoundException; use Box\Spout\Writer\Exception\SheetNotFoundException;
use Box\Spout\Writer\Exception\WriterAlreadyOpenedException; use Box\Spout\Writer\Exception\WriterAlreadyOpenedException;
@@ -25,7 +24,7 @@ abstract class WriterMultiSheetsAbstract extends WriterAbstract
/** @var ManagerFactoryInterface */ /** @var ManagerFactoryInterface */
private $managerFactory; private $managerFactory;
/** @var WorkbookManagerInterface */ /** @var WorkbookManagerInterface|null */
private $workbookManager; private $workbookManager;
/** /**
@@ -66,7 +65,7 @@ abstract class WriterMultiSheetsAbstract extends WriterAbstract
*/ */
protected function openWriter() protected function openWriter()
{ {
if (!$this->workbookManager) { if ($this->workbookManager === null) {
$this->workbookManager = $this->managerFactory->createWorkbookManager($this->optionsManager); $this->workbookManager = $this->managerFactory->createWorkbookManager($this->optionsManager);
$this->workbookManager->addNewSheetAndMakeItCurrent(); $this->workbookManager->addNewSheetAndMakeItCurrent();
} }
@@ -85,7 +84,6 @@ abstract class WriterMultiSheetsAbstract extends WriterAbstract
$externalSheets = []; $externalSheets = [];
$worksheets = $this->workbookManager->getWorksheets(); $worksheets = $this->workbookManager->getWorksheets();
/** @var Worksheet $worksheet */
foreach ($worksheets as $worksheet) { foreach ($worksheets as $worksheet) {
$externalSheets[] = $worksheet->getExternalSheet(); $externalSheets[] = $worksheet->getExternalSheet();
} }
@@ -143,7 +141,7 @@ abstract class WriterMultiSheetsAbstract extends WriterAbstract
*/ */
protected function throwIfWorkbookIsNotAvailable() protected function throwIfWorkbookIsNotAvailable()
{ {
if (!$this->workbookManager->getWorkbook()) { if ($this->workbookManager->getWorkbook() === null) {
throw new WriterNotOpenedException('The writer must be opened before performing this action.'); throw new WriterNotOpenedException('The writer must be opened before performing this action.');
} }
} }
@@ -162,7 +160,7 @@ abstract class WriterMultiSheetsAbstract extends WriterAbstract
*/ */
protected function closeWriter() protected function closeWriter()
{ {
if ($this->workbookManager) { if ($this->workbookManager !== null) {
$this->workbookManager->close($this->filePointer); $this->workbookManager->close($this->filePointer);
} }
} }
@@ -91,8 +91,7 @@ class ManagerFactory implements ManagerFactoryInterface
$styleMerger, $styleMerger,
$sharedStringsManager, $sharedStringsManager,
$stringsEscaper, $stringsEscaper,
$stringsHelper, $stringsHelper
$this->entityFactory
); );
} }
@@ -14,20 +14,20 @@ use Box\Spout\Writer\XLSX\Manager\Style\StyleManager;
*/ */
class FileSystemHelper extends \Box\Spout\Common\Helper\FileSystemHelper implements FileSystemWithRootFolderHelperInterface class FileSystemHelper extends \Box\Spout\Common\Helper\FileSystemHelper implements FileSystemWithRootFolderHelperInterface
{ {
const APP_NAME = 'Spout'; public const APP_NAME = 'Spout';
const RELS_FOLDER_NAME = '_rels'; public const RELS_FOLDER_NAME = '_rels';
const DOC_PROPS_FOLDER_NAME = 'docProps'; public const DOC_PROPS_FOLDER_NAME = 'docProps';
const XL_FOLDER_NAME = 'xl'; public const XL_FOLDER_NAME = 'xl';
const WORKSHEETS_FOLDER_NAME = 'worksheets'; public const WORKSHEETS_FOLDER_NAME = 'worksheets';
const RELS_FILE_NAME = '.rels'; public const RELS_FILE_NAME = '.rels';
const APP_XML_FILE_NAME = 'app.xml'; public const APP_XML_FILE_NAME = 'app.xml';
const CORE_XML_FILE_NAME = 'core.xml'; public const CORE_XML_FILE_NAME = 'core.xml';
const CONTENT_TYPES_XML_FILE_NAME = '[Content_Types].xml'; public const CONTENT_TYPES_XML_FILE_NAME = '[Content_Types].xml';
const WORKBOOK_XML_FILE_NAME = 'workbook.xml'; public const WORKBOOK_XML_FILE_NAME = 'workbook.xml';
const WORKBOOK_RELS_XML_FILE_NAME = 'workbook.xml.rels'; public const WORKBOOK_RELS_XML_FILE_NAME = 'workbook.xml.rels';
const STYLES_XML_FILE_NAME = 'styles.xml'; public const STYLES_XML_FILE_NAME = 'styles.xml';
/** @var ZipHelper Helper to perform tasks with Zip archive */ /** @var ZipHelper Helper to perform tasks with Zip archive */
private $zipHelper; private $zipHelper;
@@ -13,8 +13,8 @@ use Box\Spout\Writer\Common\Entity\Options;
class OptionsManager extends OptionsManagerAbstract class OptionsManager extends OptionsManagerAbstract
{ {
/** Default style font values */ /** Default style font values */
const DEFAULT_FONT_SIZE = 12; public const DEFAULT_FONT_SIZE = 12;
const DEFAULT_FONT_NAME = 'Calibri'; public const DEFAULT_FONT_NAME = 'Calibri';
/** @var StyleBuilder Style builder */ /** @var StyleBuilder Style builder */
protected $styleBuilder; protected $styleBuilder;
@@ -11,9 +11,9 @@ use Box\Spout\Common\Helper\Escaper;
*/ */
class SharedStringsManager class SharedStringsManager
{ {
const SHARED_STRINGS_FILE_NAME = 'sharedStrings.xml'; public const SHARED_STRINGS_FILE_NAME = 'sharedStrings.xml';
const SHARED_STRINGS_XML_FILE_FIRST_PART_HEADER = <<<'EOD' public const SHARED_STRINGS_XML_FILE_FIRST_PART_HEADER = <<<'EOD'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" <sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
EOD; EOD;
@@ -22,7 +22,7 @@ EOD;
* This number must be really big so that the no generated file will have more strings than that. * This number must be really big so that the no generated file will have more strings than that.
* If the strings number goes above, characters will be overwritten in an unwanted way and will corrupt the file. * If the strings number goes above, characters will be overwritten in an unwanted way and will corrupt the file.
*/ */
const DEFAULT_STRINGS_COUNT_PART = 'count="9999999999999" uniqueCount="9999999999999"'; public const DEFAULT_STRINGS_COUNT_PART = 'count="9999999999999" uniqueCount="9999999999999"';
/** @var resource Pointer to the sharedStrings.xml file */ /** @var resource Pointer to the sharedStrings.xml file */
protected $sharedStringsFilePointer; protected $sharedStringsFilePointer;
@@ -59,7 +59,7 @@ EOD;
*/ */
protected function throwIfSharedStringsFilePointerIsNotAvailable() protected function throwIfSharedStringsFilePointerIsNotAvailable()
{ {
if (!$this->sharedStringsFilePointer) { if (!is_resource($this->sharedStringsFilePointer)) {
throw new IOException('Unable to open shared strings file for writing.'); throw new IOException('Unable to open shared strings file for writing.');
} }
} }
@@ -2,6 +2,7 @@
namespace Box\Spout\Writer\XLSX\Manager\Style; namespace Box\Spout\Writer\XLSX\Manager\Style;
use Box\Spout\Common\Entity\Style\BorderPart;
use Box\Spout\Common\Entity\Style\Color; use Box\Spout\Common\Entity\Style\Color;
use Box\Spout\Common\Entity\Style\Style; use Box\Spout\Common\Entity\Style\Style;
use Box\Spout\Writer\XLSX\Helper\BorderHelper; use Box\Spout\Writer\XLSX\Helper\BorderHelper;
@@ -186,7 +187,7 @@ EOD;
$content .= '<border><left/><right/><top/><bottom/></border>'; $content .= '<border><left/><right/><top/><bottom/></border>';
foreach ($registeredBorders as $styleId) { foreach ($registeredBorders as $styleId) {
/** @var \Box\Spout\Common\Entity\Style\Style $style */ /** @var Style $style */
$style = $this->styleRegistry->getStyleFromStyleId($styleId); $style = $this->styleRegistry->getStyleFromStyleId($styleId);
$border = $style->getBorder(); $border = $style->getBorder();
$content .= '<border>'; $content .= '<border>';
@@ -196,7 +197,7 @@ EOD;
foreach ($sortOrder as $partName) { foreach ($sortOrder as $partName) {
if ($border->hasPart($partName)) { if ($border->hasPart($partName)) {
/** @var $part \Box\Spout\Common\Entity\Style\BorderPart */ /** @var BorderPart $part */
$part = $border->getPart($partName); $part = $border->getPart($partName);
$content .= BorderHelper::serializeBorderPart($part); $content .= BorderHelper::serializeBorderPart($part);
} }
@@ -10,7 +10,6 @@ use Box\Spout\Common\Exception\IOException;
use Box\Spout\Common\Helper\Escaper\XLSX as XLSXEscaper; use Box\Spout\Common\Helper\Escaper\XLSX as XLSXEscaper;
use Box\Spout\Common\Helper\StringHelper; use Box\Spout\Common\Helper\StringHelper;
use Box\Spout\Common\Manager\OptionsManagerInterface; use Box\Spout\Common\Manager\OptionsManagerInterface;
use Box\Spout\Writer\Common\Creator\InternalEntityFactory;
use Box\Spout\Writer\Common\Entity\Options; use Box\Spout\Writer\Common\Entity\Options;
use Box\Spout\Writer\Common\Entity\Worksheet; use Box\Spout\Writer\Common\Entity\Worksheet;
use Box\Spout\Writer\Common\Helper\CellHelper; use Box\Spout\Writer\Common\Helper\CellHelper;
@@ -32,9 +31,9 @@ class WorksheetManager implements WorksheetManagerInterface
* @see https://support.office.com/en-us/article/Excel-specifications-and-limits-1672b34d-7043-467e-8e27-269d656771c3 [Excel 2010] * @see https://support.office.com/en-us/article/Excel-specifications-and-limits-1672b34d-7043-467e-8e27-269d656771c3 [Excel 2010]
* @see https://support.office.com/en-us/article/Excel-specifications-and-limits-ca36e2dc-1f09-4620-b726-67c00b05040f [Excel 2013/2016] * @see https://support.office.com/en-us/article/Excel-specifications-and-limits-ca36e2dc-1f09-4620-b726-67c00b05040f [Excel 2013/2016]
*/ */
const MAX_CHARACTERS_PER_CELL = 32767; public const MAX_CHARACTERS_PER_CELL = 32767;
const SHEET_XML_FILE_HEADER = <<<'EOD' public const SHEET_XML_FILE_HEADER = <<<'EOD'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"> <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
EOD; EOD;
@@ -60,9 +59,6 @@ EOD;
/** @var StringHelper String helper */ /** @var StringHelper String helper */
private $stringHelper; private $stringHelper;
/** @var InternalEntityFactory Factory to create entities */
private $entityFactory;
/** /**
* WorksheetManager constructor. * WorksheetManager constructor.
* *
@@ -73,7 +69,6 @@ EOD;
* @param SharedStringsManager $sharedStringsManager * @param SharedStringsManager $sharedStringsManager
* @param XLSXEscaper $stringsEscaper * @param XLSXEscaper $stringsEscaper
* @param StringHelper $stringHelper * @param StringHelper $stringHelper
* @param InternalEntityFactory $entityFactory
*/ */
public function __construct( public function __construct(
OptionsManagerInterface $optionsManager, OptionsManagerInterface $optionsManager,
@@ -82,8 +77,7 @@ EOD;
StyleMerger $styleMerger, StyleMerger $styleMerger,
SharedStringsManager $sharedStringsManager, SharedStringsManager $sharedStringsManager,
XLSXEscaper $stringsEscaper, XLSXEscaper $stringsEscaper,
StringHelper $stringHelper, StringHelper $stringHelper
InternalEntityFactory $entityFactory
) { ) {
$this->shouldUseInlineStrings = $optionsManager->getOption(Options::SHOULD_USE_INLINE_STRINGS); $this->shouldUseInlineStrings = $optionsManager->getOption(Options::SHOULD_USE_INLINE_STRINGS);
$this->rowManager = $rowManager; $this->rowManager = $rowManager;
@@ -92,7 +86,6 @@ EOD;
$this->sharedStringsManager = $sharedStringsManager; $this->sharedStringsManager = $sharedStringsManager;
$this->stringsEscaper = $stringsEscaper; $this->stringsEscaper = $stringsEscaper;
$this->stringHelper = $stringHelper; $this->stringHelper = $stringHelper;
$this->entityFactory = $entityFactory;
} }
/** /**
+2 -2
View File
@@ -7,7 +7,7 @@ use Box\Spout\Common\Entity\Style\Style;
class RowTest extends \PHPUnit\Framework\TestCase class RowTest extends \PHPUnit\Framework\TestCase
{ {
/** /**
* @return \PHPUnit_Framework_MockObject_MockObject|Style * @return \PHPUnit\Framework\MockObject\MockObject|Style
*/ */
private function getStyleMock() private function getStyleMock()
{ {
@@ -15,7 +15,7 @@ class RowTest extends \PHPUnit\Framework\TestCase
} }
/** /**
* @return \PHPUnit_Framework_MockObject_MockObject|Cell * @return \PHPUnit\Framework\MockObject\MockObject|Cell
*/ */
private function getCellMock() private function getCellMock()
{ {
@@ -113,7 +113,7 @@ class BorderTest extends TestCase
$border->addPart($borderPart); $border->addPart($borderPart);
$this->assertCount(1, $border->getParts()); $this->assertCount(1, $border->getParts());
/** @var $part BorderPart */ /** @var BorderPart $part */
$part = $border->getParts()[$allowedName]; $part = $border->getParts()[$allowedName];
$this->assertEquals($allowedStyle, $part->getStyle()); $this->assertEquals($allowedStyle, $part->getStyle());
@@ -10,7 +10,7 @@ use PHPUnit\Framework\TestCase;
class CellTypeHelperTest extends TestCase class CellTypeHelperTest extends TestCase
{ {
/** /**
* @return array * @return void
*/ */
public function testIsEmpty() public function testIsEmpty()
{ {
@@ -27,7 +27,7 @@ class CellTypeHelperTest extends TestCase
} }
/** /**
* @return array * @return void
*/ */
public function testIsNonEmptyString() public function testIsNonEmptyString()
{ {
@@ -44,7 +44,7 @@ class CellTypeHelperTest extends TestCase
} }
/** /**
* @return array * @return void
*/ */
public function testIsNumeric() public function testIsNumeric()
{ {
@@ -66,7 +66,7 @@ class CellTypeHelperTest extends TestCase
} }
/** /**
* @return array * @return void
*/ */
public function testIsBoolean() public function testIsBoolean()
{ {
@@ -68,15 +68,15 @@ class EncodingHelperTest extends TestCase
$this->expectException(EncodingConversionException::class); $this->expectException(EncodingConversionException::class);
$helperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\GlobalFunctionsHelper') $helperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\GlobalFunctionsHelper')
->setMethods(['iconv', 'mb_convert_encoding']) ->onlyMethods(['iconv', 'mb_convert_encoding'])
->getMock(); ->getMock();
$helperStub->method('iconv')->willReturn(false); $helperStub->method('iconv')->willReturn(false);
$helperStub->method('mb_convert_encoding')->willReturn(false); $helperStub->method('mb_convert_encoding')->willReturn(false);
/** @var EncodingHelper $encodingHelperStub */ /** @var EncodingHelper|\PHPUnit\Framework\MockObject\MockObject|\PHPUnit\Framework\MockObject\MockObject $encodingHelperStub */
$encodingHelperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\EncodingHelper') $encodingHelperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\EncodingHelper')
->setConstructorArgs([$helperStub]) ->setConstructorArgs([$helperStub])
->setMethods(['canUseIconv', 'canUseMbString']) ->onlyMethods(['canUseIconv', 'canUseMbString'])
->getMock(); ->getMock();
$encodingHelperStub->method('canUseIconv')->willReturn($shouldUseIconv); $encodingHelperStub->method('canUseIconv')->willReturn($shouldUseIconv);
$encodingHelperStub->method('canUseMbString')->willReturn(true); $encodingHelperStub->method('canUseMbString')->willReturn(true);
@@ -91,10 +91,10 @@ class EncodingHelperTest extends TestCase
{ {
$this->expectException(EncodingConversionException::class); $this->expectException(EncodingConversionException::class);
/** @var EncodingHelper $encodingHelperStub */ /** @var EncodingHelper|\PHPUnit\Framework\MockObject\MockObject|\PHPUnit\Framework\MockObject\MockObject $encodingHelperStub */
$encodingHelperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\EncodingHelper') $encodingHelperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\EncodingHelper')
->disableOriginalConstructor() ->disableOriginalConstructor()
->setMethods(['canUseIconv', 'canUseMbString']) ->onlyMethods(['canUseIconv', 'canUseMbString'])
->getMock(); ->getMock();
$encodingHelperStub->method('canUseIconv')->willReturn(false); $encodingHelperStub->method('canUseIconv')->willReturn(false);
$encodingHelperStub->method('canUseMbString')->willReturn(false); $encodingHelperStub->method('canUseMbString')->willReturn(false);
@@ -110,10 +110,10 @@ class EncodingHelperTest extends TestCase
*/ */
public function testAttemptConversionToUTF8ShouldReturnReencodedString($shouldUseIconv) public function testAttemptConversionToUTF8ShouldReturnReencodedString($shouldUseIconv)
{ {
/** @var EncodingHelper $encodingHelperStub */ /** @var EncodingHelper|\PHPUnit\Framework\MockObject\MockObject $encodingHelperStub */
$encodingHelperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\EncodingHelper') $encodingHelperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\EncodingHelper')
->setConstructorArgs([new GlobalFunctionsHelper()]) ->setConstructorArgs([new GlobalFunctionsHelper()])
->setMethods(['canUseIconv', 'canUseMbString']) ->onlyMethods(['canUseIconv', 'canUseMbString'])
->getMock(); ->getMock();
$encodingHelperStub->method('canUseIconv')->willReturn($shouldUseIconv); $encodingHelperStub->method('canUseIconv')->willReturn($shouldUseIconv);
$encodingHelperStub->method('canUseMbString')->willReturn(true); $encodingHelperStub->method('canUseMbString')->willReturn(true);
@@ -129,10 +129,10 @@ class EncodingHelperTest extends TestCase
*/ */
public function testAttemptConversionToUTF8ShouldBeNoopWhenTargetIsUTF8() public function testAttemptConversionToUTF8ShouldBeNoopWhenTargetIsUTF8()
{ {
/** @var EncodingHelper $encodingHelperStub */ /** @var EncodingHelper|\PHPUnit\Framework\MockObject\MockObject|\PHPUnit\Framework\MockObject\MockObject $encodingHelperStub */
$encodingHelperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\EncodingHelper') $encodingHelperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\EncodingHelper')
->disableOriginalConstructor() ->disableOriginalConstructor()
->setMethods(['canUseIconv']) ->onlyMethods(['canUseIconv'])
->getMock(); ->getMock();
$encodingHelperStub->expects($this->never())->method('canUseIconv'); $encodingHelperStub->expects($this->never())->method('canUseIconv');
@@ -151,15 +151,15 @@ class EncodingHelperTest extends TestCase
$this->expectException(EncodingConversionException::class); $this->expectException(EncodingConversionException::class);
$helperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\GlobalFunctionsHelper') $helperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\GlobalFunctionsHelper')
->setMethods(['iconv', 'mb_convert_encoding']) ->onlyMethods(['iconv', 'mb_convert_encoding'])
->getMock(); ->getMock();
$helperStub->method('iconv')->willReturn(false); $helperStub->method('iconv')->willReturn(false);
$helperStub->method('mb_convert_encoding')->willReturn(false); $helperStub->method('mb_convert_encoding')->willReturn(false);
/** @var EncodingHelper $encodingHelperStub */ /** @var EncodingHelper|\PHPUnit\Framework\MockObject\MockObject|\PHPUnit\Framework\MockObject\MockObject $encodingHelperStub */
$encodingHelperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\EncodingHelper') $encodingHelperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\EncodingHelper')
->setConstructorArgs([$helperStub]) ->setConstructorArgs([$helperStub])
->setMethods(['canUseIconv', 'canUseMbString']) ->onlyMethods(['canUseIconv', 'canUseMbString'])
->getMock(); ->getMock();
$encodingHelperStub->method('canUseIconv')->willReturn($shouldUseIconv); $encodingHelperStub->method('canUseIconv')->willReturn($shouldUseIconv);
$encodingHelperStub->method('canUseMbString')->willReturn(true); $encodingHelperStub->method('canUseMbString')->willReturn(true);
@@ -174,10 +174,10 @@ class EncodingHelperTest extends TestCase
{ {
$this->expectException(EncodingConversionException::class); $this->expectException(EncodingConversionException::class);
/** @var EncodingHelper $encodingHelperStub */ /** @var EncodingHelper|\PHPUnit\Framework\MockObject\MockObject|\PHPUnit\Framework\MockObject\MockObject $encodingHelperStub */
$encodingHelperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\EncodingHelper') $encodingHelperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\EncodingHelper')
->disableOriginalConstructor() ->disableOriginalConstructor()
->setMethods(['canUseIconv', 'canUseMbString']) ->onlyMethods(['canUseIconv', 'canUseMbString'])
->getMock(); ->getMock();
$encodingHelperStub->method('canUseIconv')->willReturn(false); $encodingHelperStub->method('canUseIconv')->willReturn(false);
$encodingHelperStub->method('canUseMbString')->willReturn(false); $encodingHelperStub->method('canUseMbString')->willReturn(false);
@@ -193,10 +193,10 @@ class EncodingHelperTest extends TestCase
*/ */
public function testAttemptConversionFromUTF8ShouldReturnReencodedString($shouldUseIconv) public function testAttemptConversionFromUTF8ShouldReturnReencodedString($shouldUseIconv)
{ {
/** @var EncodingHelper $encodingHelperStub */ /** @var EncodingHelper|\PHPUnit\Framework\MockObject\MockObject $encodingHelperStub */
$encodingHelperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\EncodingHelper') $encodingHelperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\EncodingHelper')
->setConstructorArgs([new GlobalFunctionsHelper()]) ->setConstructorArgs([new GlobalFunctionsHelper()])
->setMethods(['canUseIconv', 'canUseMbString']) ->onlyMethods(['canUseIconv', 'canUseMbString'])
->getMock(); ->getMock();
$encodingHelperStub->method('canUseIconv')->willReturn($shouldUseIconv); $encodingHelperStub->method('canUseIconv')->willReturn($shouldUseIconv);
$encodingHelperStub->method('canUseMbString')->willReturn(true); $encodingHelperStub->method('canUseMbString')->willReturn(true);
@@ -212,10 +212,10 @@ class EncodingHelperTest extends TestCase
*/ */
public function testAttemptConversionFromUTF8ShouldBeNoopWhenTargetIsUTF8() public function testAttemptConversionFromUTF8ShouldBeNoopWhenTargetIsUTF8()
{ {
/** @var EncodingHelper $encodingHelperStub */ /** @var EncodingHelper|\PHPUnit\Framework\MockObject\MockObject $encodingHelperStub */
$encodingHelperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\EncodingHelper') $encodingHelperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\EncodingHelper')
->disableOriginalConstructor() ->disableOriginalConstructor()
->setMethods(['canUseIconv']) ->onlyMethods(['canUseIconv'])
->getMock(); ->getMock();
$encodingHelperStub->expects($this->never())->method('canUseIconv'); $encodingHelperStub->expects($this->never())->method('canUseIconv');
@@ -10,7 +10,7 @@ use PHPUnit\Framework\TestCase;
*/ */
class FileSystemHelperTest extends TestCase class FileSystemHelperTest extends TestCase
{ {
/** @var \Box\Spout\Writer\XLSX\Helper\FileSystemHelper */ /** @var FileSystemHelper */
protected $fileSystemHelper; protected $fileSystemHelper;
/** /**
+11 -8
View File
@@ -47,9 +47,9 @@ class ReaderTest extends TestCase
{ {
$this->expectException(IOException::class); $this->expectException(IOException::class);
/** @var \Box\Spout\Common\Helper\GlobalFunctionsHelper|\PHPUnit_Framework_MockObject_MockObject $helperStub */ /** @var \Box\Spout\Common\Helper\GlobalFunctionsHelper|\PHPUnit\Framework\MockObject\MockObject $helperStub */
$helperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\GlobalFunctionsHelper') $helperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\GlobalFunctionsHelper')
->setMethods(['is_readable']) ->onlyMethods(['is_readable'])
->getMock(); ->getMock();
$helperStub->method('is_readable')->willReturn(false); $helperStub->method('is_readable')->willReturn(false);
@@ -66,9 +66,9 @@ class ReaderTest extends TestCase
{ {
$this->expectException(IOException::class); $this->expectException(IOException::class);
/** @var \Box\Spout\Common\Helper\GlobalFunctionsHelper|\PHPUnit_Framework_MockObject_MockObject $helperStub */ /** @var \Box\Spout\Common\Helper\GlobalFunctionsHelper|\PHPUnit\Framework\MockObject\MockObject $helperStub */
$helperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\GlobalFunctionsHelper') $helperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\GlobalFunctionsHelper')
->setMethods(['fopen']) ->onlyMethods(['fopen'])
->getMock(); ->getMock();
$helperStub->method('fopen')->willReturn(false); $helperStub->method('fopen')->willReturn(false);
@@ -237,7 +237,9 @@ class ReaderTest extends TestCase
public function testReadShouldNotTruncateLineBreak() public function testReadShouldNotTruncateLineBreak()
{ {
$allRows = $this->getAllRowsForFile('csv_with_line_breaks.csv'); $allRows = $this->getAllRowsForFile('csv_with_line_breaks.csv');
$this->assertEquals("This is,\na comma", $allRows[0][0]);
$newLine = PHP_EOL; // to support both Unix and Windows
$this->assertEquals("This is,{$newLine}a comma", $allRows[0][0]);
} }
/** /**
@@ -302,9 +304,9 @@ class ReaderTest extends TestCase
$allRows = []; $allRows = [];
$resourcePath = $this->getResourcePath($fileName); $resourcePath = $this->getResourcePath($fileName);
/** @var \Box\Spout\Common\Helper\GlobalFunctionsHelper|\PHPUnit_Framework_MockObject_MockObject $helperStub */ /** @var \Box\Spout\Common\Helper\GlobalFunctionsHelper|\PHPUnit\Framework\MockObject\MockObject $helperStub */
$helperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\GlobalFunctionsHelper') $helperStub = $this->getMockBuilder('\Box\Spout\Common\Helper\GlobalFunctionsHelper')
->setMethods(['function_exists']) ->onlyMethods(['function_exists'])
->getMock(); ->getMock();
$returnValueMap = [ $returnValueMap = [
@@ -419,10 +421,11 @@ class ReaderTest extends TestCase
{ {
$allRows = $this->getAllRowsForFile('sheet_with_untrimmed_strings.csv'); $allRows = $this->getAllRowsForFile('sheet_with_untrimmed_strings.csv');
$newLine = PHP_EOL; // to support both Unix and Windows
$expectedRows = [ $expectedRows = [
['A'], ['A'],
[' A '], [' A '],
["\n\tA\n\t"], ["$newLine\tA$newLine\t"],
]; ];
$this->assertEquals($expectedRows, $allRows, 'Cell values should not be trimmed'); $this->assertEquals($expectedRows, $allRows, 'Cell values should not be trimmed');
+3 -3
View File
@@ -9,10 +9,10 @@ namespace Box\Spout\Reader\CSV;
*/ */
class SpoutTestStream class SpoutTestStream
{ {
const CLASS_NAME = __CLASS__; public const CLASS_NAME = __CLASS__;
const PATH_TO_CSV_RESOURCES = 'tests/resources/csv/'; public const PATH_TO_CSV_RESOURCES = 'tests/resources/csv/';
const CSV_EXTENSION = '.csv'; public const CSV_EXTENSION = '.csv';
/** @var int */ /** @var int */
private $position; private $position;
@@ -79,7 +79,7 @@ class CellValueFormatterTest extends TestCase
->method('getAttribute') ->method('getAttribute')
->will($this->returnValueMap([ ->will($this->returnValueMap([
[CellValueFormatter::XML_ATTRIBUTE_TYPE, CellValueFormatter::CELL_TYPE_NUMERIC], [CellValueFormatter::XML_ATTRIBUTE_TYPE, CellValueFormatter::CELL_TYPE_NUMERIC],
[CellValueFormatter::XML_ATTRIBUTE_STYLE_ID, 123], [CellValueFormatter::XML_ATTRIBUTE_STYLE_ID, '123'],
])); ]));
$nodeMock $nodeMock
@@ -88,7 +88,7 @@ class CellValueFormatterTest extends TestCase
->with(CellValueFormatter::XML_NODE_VALUE) ->with(CellValueFormatter::XML_NODE_VALUE)
->will($this->returnValue($nodeListMock)); ->will($this->returnValue($nodeListMock));
/** @var StyleManager|\PHPUnit_Framework_MockObject_MockObject $styleManagerMock */ /** @var StyleManager|\PHPUnit\Framework\MockObject\MockObject $styleManagerMock */
$styleManagerMock = $this->createMock(StyleManager::class); $styleManagerMock = $this->createMock(StyleManager::class);
$styleManagerMock $styleManagerMock
@@ -149,7 +149,7 @@ class CellValueFormatterTest extends TestCase
*/ */
public function testFormatNumericCellValueWithNumbers($value, $expectedFormattedValue, $expectedType) public function testFormatNumericCellValueWithNumbers($value, $expectedFormattedValue, $expectedType)
{ {
/** @var StyleManager|\PHPUnit_Framework_MockObject_MockObject $styleManagerMock */ /** @var StyleManager|\PHPUnit\Framework\MockObject\MockObject $styleManagerMock */
$styleManagerMock = $this->createMock(StyleManager::class); $styleManagerMock = $this->createMock(StyleManager::class);
$styleManagerMock $styleManagerMock
->expects($this->once()) ->expects($this->once())
@@ -36,17 +36,17 @@ class CachingStrategyFactoryTest extends TestCase
*/ */
public function testCreateBestCachingStrategy($sharedStringsUniqueCount, $memoryLimitInKB, $expectedStrategyClassName) public function testCreateBestCachingStrategy($sharedStringsUniqueCount, $memoryLimitInKB, $expectedStrategyClassName)
{ {
/** @var CachingStrategyFactory|\PHPUnit_Framework_MockObject_MockObject $factoryStub */ /** @var CachingStrategyFactory|\PHPUnit\Framework\MockObject\MockObject $factoryStub */
$factoryStub = $this $factoryStub = $this
->getMockBuilder('\Box\Spout\Reader\XLSX\Manager\SharedStringsCaching\CachingStrategyFactory') ->getMockBuilder('\Box\Spout\Reader\XLSX\Manager\SharedStringsCaching\CachingStrategyFactory')
->disableOriginalConstructor() ->disableOriginalConstructor()
->setMethods(['getMemoryLimitInKB']) ->onlyMethods(['getMemoryLimitInKB'])
->getMock(); ->getMock();
$factoryStub->method('getMemoryLimitInKB')->willReturn($memoryLimitInKB); $factoryStub->method('getMemoryLimitInKB')->willReturn($memoryLimitInKB);
$tempFolder = sys_get_temp_dir(); $tempFolder = sys_get_temp_dir();
$helperFactory = new HelperFactory($factoryStub); $helperFactory = new HelperFactory();
$strategy = $factoryStub->createBestCachingStrategy($sharedStringsUniqueCount, $tempFolder, $helperFactory); $strategy = $factoryStub->createBestCachingStrategy($sharedStringsUniqueCount, $tempFolder, $helperFactory);
$fullExpectedStrategyClassName = 'Box\Spout\Reader\XLSX\Manager\SharedStringsCaching\\' . $expectedStrategyClassName; $fullExpectedStrategyClassName = 'Box\Spout\Reader\XLSX\Manager\SharedStringsCaching\\' . $expectedStrategyClassName;
@@ -84,11 +84,11 @@ class CachingStrategyFactoryTest extends TestCase
*/ */
public function testGetMemoryLimitInKB($memoryLimitFormatted, $expectedMemoryLimitInKB) public function testGetMemoryLimitInKB($memoryLimitFormatted, $expectedMemoryLimitInKB)
{ {
/** @var CachingStrategyFactory|\PHPUnit_Framework_MockObject_MockObject $factoryStub */ /** @var CachingStrategyFactory|\PHPUnit\Framework\MockObject\MockObject $factoryStub */
$factoryStub = $this $factoryStub = $this
->getMockBuilder('\Box\Spout\Reader\XLSX\Manager\SharedStringsCaching\CachingStrategyFactory') ->getMockBuilder('\Box\Spout\Reader\XLSX\Manager\SharedStringsCaching\CachingStrategyFactory')
->disableOriginalConstructor() ->disableOriginalConstructor()
->setMethods(['getMemoryLimitFromIni']) ->onlyMethods(['getMemoryLimitFromIni'])
->getMock(); ->getMock();
$factoryStub->method('getMemoryLimitFromIni')->willReturn($memoryLimitFormatted); $factoryStub->method('getMemoryLimitFromIni')->willReturn($memoryLimitFormatted);
@@ -19,7 +19,7 @@ class SharedStringsManagerTest extends TestCase
{ {
use TestUsingResource; use TestUsingResource;
/** @var SharedStringsManager */ /** @var SharedStringsManager|null */
private $sharedStringsManager; private $sharedStringsManager;
/** /**
@@ -21,10 +21,10 @@ class StyleManagerTest extends TestCase
$workbookRelationshipsManager = $this->createMock(WorkbookRelationshipsManager::class); $workbookRelationshipsManager = $this->createMock(WorkbookRelationshipsManager::class);
$workbookRelationshipsManager->method('hasStylesXMLFile')->willReturn(true); $workbookRelationshipsManager->method('hasStylesXMLFile')->willReturn(true);
/** @var StyleManager $styleManager */ /** @var StyleManager|\PHPUnit\Framework\MockObject\MockObject $styleManager */
$styleManager = $this->getMockBuilder('\Box\Spout\Reader\XLSX\Manager\StyleManager') $styleManager = $this->getMockBuilder('\Box\Spout\Reader\XLSX\Manager\StyleManager')
->setConstructorArgs(['/path/to/file.xlsx', $workbookRelationshipsManager, $entityFactory]) ->setConstructorArgs(['/path/to/file.xlsx', $workbookRelationshipsManager, $entityFactory])
->setMethods(['getCustomNumberFormats', 'getStylesAttributes']) ->onlyMethods(['getCustomNumberFormats', 'getStylesAttributes'])
->getMock(); ->getMock();
$styleManager->method('getStylesAttributes')->willReturn($styleAttributes); $styleManager->method('getStylesAttributes')->willReturn($styleAttributes);
+1 -2
View File
@@ -62,7 +62,7 @@ class ReflectionHelper
// to prevent side-effects in later tests, we need to remember the original value and reset it on tear down // to prevent side-effects in later tests, we need to remember the original value and reset it on tear down
// @NOTE: we need to check isset in case the original value was null or array() // @NOTE: we need to check isset in case the original value was null or array()
if ($saveOriginalValue && (!isset(self::$privateVarsToReset[$class]) || !isset(self::$privateVarsToReset[$class][$name]))) { if ($saveOriginalValue && (!isset(self::$privateVarsToReset[$class]) || !isset(self::$privateVarsToReset[$class][$valueName]))) {
self::$privateVarsToReset[$class][$valueName] = $reflectionProperty->getValue(); self::$privateVarsToReset[$class][$valueName] = $reflectionProperty->getValue();
} }
$reflectionProperty->setValue($value); $reflectionProperty->setValue($value);
@@ -95,7 +95,6 @@ class ReflectionHelper
* *
* @param object $object * @param object $object
* @param string $methodName * @param string $methodName
* @param *mixed|null $params
* *
* @return mixed|null * @return mixed|null
*/ */
+1 -1
View File
@@ -193,7 +193,7 @@ class WriterTest extends TestCase
* @param string $fieldDelimiter * @param string $fieldDelimiter
* @param string $fieldEnclosure * @param string $fieldEnclosure
* @param bool $shouldAddBOM * @param bool $shouldAddBOM
* @return string|null * @return string
*/ */
private function writeToCsvFileAndReturnWrittenContent($allRows, $fileName, $fieldDelimiter = ',', $fieldEnclosure = '"', $shouldAddBOM = true) private function writeToCsvFileAndReturnWrittenContent($allRows, $fileName, $fieldDelimiter = ',', $fieldEnclosure = '"', $shouldAddBOM = true)
{ {
+1 -1
View File
@@ -95,7 +95,7 @@ class SheetTest extends TestCase
/** /**
* @param string $fileName * @param string $fileName
* @param string $sheetName * @param string $sheetName
* @return Sheet * @return void
*/ */
private function writeDataAndReturnSheetWithCustomName($fileName, $sheetName) private function writeDataAndReturnSheetWithCustomName($fileName, $sheetName)
{ {
+15 -3
View File
@@ -132,7 +132,7 @@ class WriterTest extends TestCase
$writer->addRows($dataRows); $writer->addRows($dataRows);
$this->fail('Exception should have been thrown'); $this->fail('Exception should have been thrown');
} catch (SpoutException $e) { } catch (SpoutException $e) {
$this->assertFileNotExists($fileName, 'Output file should have been deleted'); $this->assertFileDoesNotExist($fileName, 'Output file should have been deleted');
$numFiles = iterator_count(new \FilesystemIterator($tempFolderPath, \FilesystemIterator::SKIP_DOTS)); $numFiles = iterator_count(new \FilesystemIterator($tempFolderPath, \FilesystemIterator::SKIP_DOTS));
$this->assertEquals(0, $numFiles, 'All temp files should have been deleted'); $this->assertEquals(0, $numFiles, 'All temp files should have been deleted');
@@ -291,12 +291,19 @@ class WriterTest extends TestCase
// Installed locales differ from one system to another, so we can't pick // Installed locales differ from one system to another, so we can't pick
// a given locale. // a given locale.
$supportedLocales = explode("\n", shell_exec('locale -a')); $supportedLocales = explode("\n", shell_exec('locale -a'));
$foundCommaLocale = false;
foreach ($supportedLocales as $supportedLocale) { foreach ($supportedLocales as $supportedLocale) {
\setlocale(LC_ALL, $supportedLocale); \setlocale(LC_ALL, $supportedLocale);
if (\localeconv()['decimal_point'] === ',') { if (\localeconv()['decimal_point'] === ',') {
$foundCommaLocale = true;
break; break;
} }
} }
if (!$foundCommaLocale) {
$this->markTestSkipped('No locale with comma decimal separator');
}
$this->assertEquals(',', \localeconv()['decimal_point']); $this->assertEquals(',', \localeconv()['decimal_point']);
$fileName = 'test_add_row_should_support_float_values_in_different_locale.xlsx'; $fileName = 'test_add_row_should_support_float_values_in_different_locale.xlsx';
@@ -306,8 +313,8 @@ class WriterTest extends TestCase
$this->writeToODSFile($dataRows, $fileName); $this->writeToODSFile($dataRows, $fileName);
$this->assertValueWasNotWrittenToSheet($fileName, 1, "1234,5"); $this->assertValueWasNotWrittenToSheet($fileName, 1, '1234,5');
$this->assertValueWasWrittenToSheet($fileName, 1, "1234.5"); $this->assertValueWasWrittenToSheet($fileName, 1, '1234.5');
} finally { } finally {
// reset locale // reset locale
\setlocale(LC_ALL, $previousLocale); \setlocale(LC_ALL, $previousLocale);
@@ -341,6 +348,7 @@ class WriterTest extends TestCase
$fileName = 'test_add_row_should_use_number_columns_repeated.ods'; $fileName = 'test_add_row_should_use_number_columns_repeated.ods';
$this->writeToODSFile($this->createRowsFromValues([$dataRow]), $fileName); $this->writeToODSFile($this->createRowsFromValues([$dataRow]), $fileName);
/** @var \DOMElement $sheetXmlNode */
$sheetXmlNode = $this->getSheetXmlNode($fileName, 1); $sheetXmlNode = $this->getSheetXmlNode($fileName, 1);
$tableCellNodes = $sheetXmlNode->getElementsByTagName('table-cell'); $tableCellNodes = $sheetXmlNode->getElementsByTagName('table-cell');
@@ -511,6 +519,10 @@ class WriterTest extends TestCase
*/ */
public function testGeneratedFileShouldHaveTheCorrectMimeType() public function testGeneratedFileShouldHaveTheCorrectMimeType()
{ {
if (!function_exists('finfo')) {
$this->markTestSkipped('finfo is not available on this system (possibly running on Windows where the DLL needs to be added explicitly to the php.ini)');
}
$fileName = 'test_mime_type.ods'; $fileName = 'test_mime_type.ods';
$resourcePath = $this->getGeneratedResourcePath($fileName); $resourcePath = $this->getGeneratedResourcePath($fileName);
$dataRow = ['foo']; $dataRow = ['foo'];
+16 -7
View File
@@ -88,6 +88,7 @@ class WriterWithStyleTest extends TestCase
$this->assertCount(3, $cellStyleElements, 'There should be 3 separate cell styles, including the default one.'); $this->assertCount(3, $cellStyleElements, 'There should be 3 separate cell styles, including the default one.');
// Second font should contain data from the first created style // Second font should contain data from the first created style
/** @var \DOMElement $customFont1Element */
$customFont1Element = $cellStyleElements[1]; $customFont1Element = $cellStyleElements[1];
$this->assertFirstChildHasAttributeEquals('bold', $customFont1Element, 'text-properties', 'fo:font-weight'); $this->assertFirstChildHasAttributeEquals('bold', $customFont1Element, 'text-properties', 'fo:font-weight');
$this->assertFirstChildHasAttributeEquals('italic', $customFont1Element, 'text-properties', 'fo:font-style'); $this->assertFirstChildHasAttributeEquals('italic', $customFont1Element, 'text-properties', 'fo:font-style');
@@ -95,6 +96,7 @@ class WriterWithStyleTest extends TestCase
$this->assertFirstChildHasAttributeEquals('solid', $customFont1Element, 'text-properties', 'style:text-line-through-style'); $this->assertFirstChildHasAttributeEquals('solid', $customFont1Element, 'text-properties', 'style:text-line-through-style');
// Third font should contain data from the second created style // Third font should contain data from the second created style
/** @var \DOMElement $customFont2Element */
$customFont2Element = $cellStyleElements[2]; $customFont2Element = $cellStyleElements[2];
$this->assertFirstChildHasAttributeEquals('15pt', $customFont2Element, 'text-properties', 'fo:font-size'); $this->assertFirstChildHasAttributeEquals('15pt', $customFont2Element, 'text-properties', 'fo:font-size');
$this->assertFirstChildHasAttributeEquals('#' . Color::RED, $customFont2Element, 'text-properties', 'fo:color'); $this->assertFirstChildHasAttributeEquals('#' . Color::RED, $customFont2Element, 'text-properties', 'fo:color');
@@ -397,7 +399,7 @@ class WriterWithStyleTest extends TestCase
/** /**
* @param string $fileName * @param string $fileName
* @return \DOMNode[] * @return \DOMElement[]
*/ */
private function getCellElementsFromContentXmlFile($fileName) private function getCellElementsFromContentXmlFile($fileName)
{ {
@@ -410,7 +412,9 @@ class WriterWithStyleTest extends TestCase
while ($xmlReader->read()) { while ($xmlReader->read()) {
if ($xmlReader->isPositionedOnStartingNode('table:table-cell') && $xmlReader->getAttribute('office:value-type') !== null) { if ($xmlReader->isPositionedOnStartingNode('table:table-cell') && $xmlReader->getAttribute('office:value-type') !== null) {
$cellElements[] = $xmlReader->expand(); /** @var \DOMElement $cellElement */
$cellElement = $xmlReader->expand();
$cellElements[] = $cellElement;
} }
} }
@@ -421,7 +425,7 @@ class WriterWithStyleTest extends TestCase
/** /**
* @param string $fileName * @param string $fileName
* @return \DOMNode[] * @return \DOMElement[]
*/ */
private function getCellStyleElementsFromContentXmlFile($fileName) private function getCellStyleElementsFromContentXmlFile($fileName)
{ {
@@ -434,7 +438,9 @@ class WriterWithStyleTest extends TestCase
while ($xmlReader->read()) { while ($xmlReader->read()) {
if ($xmlReader->isPositionedOnStartingNode('style:style') && $xmlReader->getAttribute('style:family') === 'table-cell') { if ($xmlReader->isPositionedOnStartingNode('style:style') && $xmlReader->getAttribute('style:family') === 'table-cell') {
$cellStyleElements[] = $xmlReader->expand(); /** @var \DOMElement $cellStyleElement */
$cellStyleElement = $xmlReader->expand();
$cellStyleElements[] = $cellStyleElement;
} }
} }
@@ -446,7 +452,7 @@ class WriterWithStyleTest extends TestCase
/** /**
* @param string $fileName * @param string $fileName
* @param string $section * @param string $section
* @return \DomNode * @return \DOMElement
*/ */
private function getXmlSectionFromStylesXmlFile($fileName, $section) private function getXmlSectionFromStylesXmlFile($fileName, $section)
{ {
@@ -456,12 +462,15 @@ class WriterWithStyleTest extends TestCase
$xmlReader->openFileInZip($resourcePath, 'styles.xml'); $xmlReader->openFileInZip($resourcePath, 'styles.xml');
$xmlReader->readUntilNodeFound($section); $xmlReader->readUntilNodeFound($section);
return $xmlReader->expand(); /** @var \DOMElement $element */
$element = $xmlReader->expand();
return $element;
} }
/** /**
* @param string $expectedValue * @param string $expectedValue
* @param \DOMNode $parentElement * @param \DOMElement $parentElement
* @param string $childTagName * @param string $childTagName
* @param string $attributeName * @param string $attributeName
* @return void * @return void
@@ -40,7 +40,7 @@ class StyleManagerTest extends TestCase
{ {
$styleRegistryMock = $this->getMockBuilder(StyleRegistry::class) $styleRegistryMock = $this->getMockBuilder(StyleRegistry::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->setMethods(['getFillIdForStyleId', 'getBorderIdForStyleId']) ->onlyMethods(['getFillIdForStyleId', 'getBorderIdForStyleId'])
->getMock(); ->getMock();
$styleRegistryMock $styleRegistryMock
+1 -1
View File
@@ -102,7 +102,7 @@ class WriterPerfTest extends TestCase
/** /**
* @param string $filePath * @param string $filePath
* @return string * @return int
*/ */
private function getLasRowNumberForFile($filePath) private function getLasRowNumberForFile($filePath)
{ {
+14 -3
View File
@@ -163,7 +163,7 @@ class WriterTest extends TestCase
$writer->addRows($dataRows); $writer->addRows($dataRows);
$this->fail('Exception should have been thrown'); $this->fail('Exception should have been thrown');
} catch (SpoutException $e) { } catch (SpoutException $e) {
$this->assertFileNotExists($fileName, 'Output file should have been deleted'); $this->assertFileDoesNotExist($fileName, 'Output file should have been deleted');
$numFiles = iterator_count(new \FilesystemIterator($tempFolderPath, \FilesystemIterator::SKIP_DOTS)); $numFiles = iterator_count(new \FilesystemIterator($tempFolderPath, \FilesystemIterator::SKIP_DOTS));
$this->assertEquals(0, $numFiles, 'All temp files should have been deleted'); $this->assertEquals(0, $numFiles, 'All temp files should have been deleted');
@@ -406,12 +406,19 @@ class WriterTest extends TestCase
// Installed locales differ from one system to another, so we can't pick // Installed locales differ from one system to another, so we can't pick
// a given locale. // a given locale.
$supportedLocales = explode("\n", shell_exec('locale -a')); $supportedLocales = explode("\n", shell_exec('locale -a'));
$foundCommaLocale = false;
foreach ($supportedLocales as $supportedLocale) { foreach ($supportedLocales as $supportedLocale) {
\setlocale(LC_ALL, $supportedLocale); \setlocale(LC_ALL, $supportedLocale);
if (\localeconv()['decimal_point'] === ',') { if (\localeconv()['decimal_point'] === ',') {
$foundCommaLocale = true;
break; break;
} }
} }
if (!$foundCommaLocale) {
$this->markTestSkipped('No locale with comma decimal separator');
}
$this->assertEquals(',', \localeconv()['decimal_point']); $this->assertEquals(',', \localeconv()['decimal_point']);
$fileName = 'test_add_row_should_support_float_values_in_different_locale.xlsx'; $fileName = 'test_add_row_should_support_float_values_in_different_locale.xlsx';
@@ -421,8 +428,8 @@ class WriterTest extends TestCase
$this->writeToXLSXFile($dataRows, $fileName, $shouldUseInlineStrings = false); $this->writeToXLSXFile($dataRows, $fileName, $shouldUseInlineStrings = false);
$this->assertInlineDataWasNotWrittenToSheet($fileName, 1, "1234,5"); $this->assertInlineDataWasNotWrittenToSheet($fileName, 1, '1234,5');
$this->assertInlineDataWasWrittenToSheet($fileName, 1, "1234.5"); $this->assertInlineDataWasWrittenToSheet($fileName, 1, '1234.5');
} finally { } finally {
// reset locale // reset locale
\setlocale(LC_ALL, $previousLocale); \setlocale(LC_ALL, $previousLocale);
@@ -568,6 +575,10 @@ class WriterTest extends TestCase
*/ */
public function testGeneratedFileShouldHaveTheCorrectMimeType() public function testGeneratedFileShouldHaveTheCorrectMimeType()
{ {
if (!function_exists('finfo')) {
$this->markTestSkipped('finfo is not available on this system (possibly running on Windows where the DLL needs to be added explicitly to the php.ini)');
}
$fileName = 'test_mime_type.xlsx'; $fileName = 'test_mime_type.xlsx';
$resourcePath = $this->getGeneratedResourcePath($fileName); $resourcePath = $this->getGeneratedResourcePath($fileName);
$dataRows = $this->createRowsFromValues([['foo']]); $dataRows = $this->createRowsFromValues([['foo']]);
+21 -10
View File
@@ -92,6 +92,7 @@ class WriterWithStyleTest extends TestCase
$this->assertEquals(3, $fontElements->length, 'There should be 3 associated "font" elements, including the default one.'); $this->assertEquals(3, $fontElements->length, 'There should be 3 associated "font" elements, including the default one.');
// First font should be the default one // First font should be the default one
/** @var \DOMElement $defaultFontElement */
$defaultFontElement = $fontElements->item(0); $defaultFontElement = $fontElements->item(0);
$this->assertChildrenNumEquals(3, $defaultFontElement, 'The default font should only have 3 properties.'); $this->assertChildrenNumEquals(3, $defaultFontElement, 'The default font should only have 3 properties.');
$this->assertFirstChildHasAttributeEquals((string) OptionsManager::DEFAULT_FONT_SIZE, $defaultFontElement, 'sz', 'val'); $this->assertFirstChildHasAttributeEquals((string) OptionsManager::DEFAULT_FONT_SIZE, $defaultFontElement, 'sz', 'val');
@@ -99,6 +100,7 @@ class WriterWithStyleTest extends TestCase
$this->assertFirstChildHasAttributeEquals(OptionsManager::DEFAULT_FONT_NAME, $defaultFontElement, 'name', 'val'); $this->assertFirstChildHasAttributeEquals(OptionsManager::DEFAULT_FONT_NAME, $defaultFontElement, 'name', 'val');
// Second font should contain data from the first created style // Second font should contain data from the first created style
/** @var \DOMElement $secondFontElement */
$secondFontElement = $fontElements->item(1); $secondFontElement = $fontElements->item(1);
$this->assertChildrenNumEquals(7, $secondFontElement, 'The font should only have 7 properties (4 custom styles + 3 default styles).'); $this->assertChildrenNumEquals(7, $secondFontElement, 'The font should only have 7 properties (4 custom styles + 3 default styles).');
$this->assertChildExists($secondFontElement, 'b'); $this->assertChildExists($secondFontElement, 'b');
@@ -110,6 +112,7 @@ class WriterWithStyleTest extends TestCase
$this->assertFirstChildHasAttributeEquals(OptionsManager::DEFAULT_FONT_NAME, $secondFontElement, 'name', 'val'); $this->assertFirstChildHasAttributeEquals(OptionsManager::DEFAULT_FONT_NAME, $secondFontElement, 'name', 'val');
// Third font should contain data from the second created style // Third font should contain data from the second created style
/** @var \DOMElement $thirdFontElement */
$thirdFontElement = $fontElements->item(2); $thirdFontElement = $fontElements->item(2);
$this->assertChildrenNumEquals(3, $thirdFontElement, 'The font should only have 3 properties.'); $this->assertChildrenNumEquals(3, $thirdFontElement, 'The font should only have 3 properties.');
$this->assertFirstChildHasAttributeEquals('15', $thirdFontElement, 'sz', 'val'); $this->assertFirstChildHasAttributeEquals('15', $thirdFontElement, 'sz', 'val');
@@ -359,7 +362,9 @@ class WriterWithStyleTest extends TestCase
$styleXfsElements = $this->getXmlSectionFromStylesXmlFile($fileName, 'cellXfs'); $styleXfsElements = $this->getXmlSectionFromStylesXmlFile($fileName, 'cellXfs');
$this->assertEquals(2, $styleXfsElements->getAttribute('count'), '2 cell xfs present - a default one and a custom one'); $this->assertEquals(2, $styleXfsElements->getAttribute('count'), '2 cell xfs present - a default one and a custom one');
$customFillId = $styleXfsElements->lastChild->getAttribute('fillId'); /** @var \DOMElement $lastChildElement */
$lastChildElement = $styleXfsElements->lastChild;
$customFillId = $lastChildElement->getAttribute('fillId');
$this->assertEquals(2, (int) $customFillId, 'The custom fill id should have the index 2'); $this->assertEquals(2, (int) $customFillId, 'The custom fill id should have the index 2');
} }
@@ -394,10 +399,14 @@ class WriterWithStyleTest extends TestCase
'3 cell xfs present - a default one and two custom ones' '3 cell xfs present - a default one and two custom ones'
); );
$firstCustomId = $styleXfsElements->childNodes->item(1)->getAttribute('fillId'); /** @var \DOMElement $styleXfsElementChild1 */
$styleXfsElementChild1 = $styleXfsElements->childNodes->item(1);
$firstCustomId = $styleXfsElementChild1->getAttribute('fillId');
$this->assertEquals(2, (int) $firstCustomId, 'The first custom fill id should have the index 2'); $this->assertEquals(2, (int) $firstCustomId, 'The first custom fill id should have the index 2');
$secondCustomId = $styleXfsElements->childNodes->item(2)->getAttribute('fillId'); /** @var \DOMElement $styleXfsElementChild2 */
$styleXfsElementChild2 = $styleXfsElements->childNodes->item(2);
$secondCustomId = $styleXfsElementChild2->getAttribute('fillId');
$this->assertEquals(2, (int) $secondCustomId, 'The second custom fill id should have the index 2'); $this->assertEquals(2, (int) $secondCustomId, 'The second custom fill id should have the index 2');
} }
@@ -468,7 +477,6 @@ class WriterWithStyleTest extends TestCase
$borderParts = $borderNode->childNodes; $borderParts = $borderNode->childNodes;
$ordering = []; $ordering = [];
/** @var \DOMText $part */
foreach ($borderParts as $part) { foreach ($borderParts as $part) {
if ($part instanceof \DOMElement) { if ($part instanceof \DOMElement) {
$ordering[] = $part->nodeName; $ordering[] = $part->nodeName;
@@ -607,7 +615,7 @@ class WriterWithStyleTest extends TestCase
/** /**
* @param string $fileName * @param string $fileName
* @param string $section * @param string $section
* @return \DomElement * @return \DOMElement
*/ */
private function getXmlSectionFromStylesXmlFile($fileName, $section) private function getXmlSectionFromStylesXmlFile($fileName, $section)
{ {
@@ -617,6 +625,7 @@ class WriterWithStyleTest extends TestCase
$xmlReader->openFileInZip($resourcePath, 'xl/styles.xml'); $xmlReader->openFileInZip($resourcePath, 'xl/styles.xml');
$xmlReader->readUntilNodeFound($section); $xmlReader->readUntilNodeFound($section);
/** @var \DOMElement $xmlSection */
$xmlSection = $xmlReader->expand(); $xmlSection = $xmlReader->expand();
$xmlReader->close(); $xmlReader->close();
@@ -626,7 +635,7 @@ class WriterWithStyleTest extends TestCase
/** /**
* @param string $fileName * @param string $fileName
* @return \DOMNode[] * @return \DOMElement[]
*/ */
private function getCellElementsFromSheetXmlFile($fileName) private function getCellElementsFromSheetXmlFile($fileName)
{ {
@@ -639,7 +648,9 @@ class WriterWithStyleTest extends TestCase
while ($xmlReader->read()) { while ($xmlReader->read()) {
if ($xmlReader->isPositionedOnStartingNode('c')) { if ($xmlReader->isPositionedOnStartingNode('c')) {
$cellElements[] = $xmlReader->expand(); /** @var \DOMElement $cellElement */
$cellElement = $xmlReader->expand();
$cellElements[] = $cellElement;
} }
} }
@@ -650,7 +661,7 @@ class WriterWithStyleTest extends TestCase
/** /**
* @param string $expectedValue * @param string $expectedValue
* @param \DOMNode $parentElement * @param \DOMElement $parentElement
* @param string $childTagName * @param string $childTagName
* @param string $attributeName * @param string $attributeName
* @return void * @return void
@@ -662,7 +673,7 @@ class WriterWithStyleTest extends TestCase
/** /**
* @param int $expectedNumber * @param int $expectedNumber
* @param \DOMNode $parentElement * @param \DOMElement $parentElement
* @param string $message * @param string $message
* @return void * @return void
*/ */
@@ -672,7 +683,7 @@ class WriterWithStyleTest extends TestCase
} }
/** /**
* @param \DOMNode $parentElement * @param \DOMElement $parentElement
* @param string $childTagName * @param string $childTagName
* @return void * @return void
*/ */