From afb4a1af9bbfa38528907f4f96b934ad0f8133be Mon Sep 17 00:00:00 2001 From: atymic Date: Fri, 1 Sep 2023 15:59:50 +1000 Subject: [PATCH 1/5] fix: configure reader/writer options spout v4 (#318) --- src/Exportable.php | 6 ++-- src/FastExcel.php | 63 +++++++++++++++++++++------------------- src/Importable.php | 5 ++-- tests/FastExcelTest.php | 30 +++++++++++++++++++ tests/test-dates.xlsx | Bin 0 -> 8701 bytes 5 files changed, 69 insertions(+), 35 deletions(-) create mode 100644 tests/test-dates.xlsx diff --git a/src/Exportable.php b/src/Exportable.php index 4ae7e44..18ad4f2 100644 --- a/src/Exportable.php +++ b/src/Exportable.php @@ -8,8 +8,8 @@ use InvalidArgumentException; use OpenSpout\Common\Entity\Row; use OpenSpout\Common\Entity\Style\Style; +use OpenSpout\Writer\Common\AbstractOptions; use OpenSpout\Writer\Common\Creator\WriterEntityFactory; -use OpenSpout\Writer\XLSX\Writer; /** * Trait Exportable. @@ -27,11 +27,11 @@ trait Exportable private $rows_style; /** - * @param \OpenSpout\Reader\ReaderInterface|\OpenSpout\Writer\WriterInterface $reader_or_writer + * @param AbstractOptions $options * * @return mixed */ - abstract protected function setOptions(&$reader_or_writer); + abstract protected function setOptions(&$options); /** * @param string $path diff --git a/src/FastExcel.php b/src/FastExcel.php index c09fdd7..d350ebb 100644 --- a/src/FastExcel.php +++ b/src/FastExcel.php @@ -5,11 +5,8 @@ use Generator; use Illuminate\Support\Collection; use OpenSpout\Reader\CSV\Options as CsvReaderOptions; -use OpenSpout\Reader\CSV\Reader; -use OpenSpout\Reader\ReaderInterface; +use OpenSpout\Writer\Common\AbstractOptions; use OpenSpout\Writer\CSV\Options as CsvWriterOptions; -use OpenSpout\Writer\CSV\Writer; -use OpenSpout\Writer\WriterInterface; /** * Class FastExcel. @@ -57,12 +54,7 @@ class FastExcel /** * @var callable */ - protected $reader_configurator = null; - - /** - * @var callable - */ - protected $writer_configurator = null; + protected $options_configurator = null; /** * FastExcel constructor. @@ -161,11 +153,12 @@ public function configureCsv($delimiter = ',', $enclosure = '"', $encoding = 'UT * @param callable|null $callback * * @return $this + * + * @deprecated Has no effect with spout v4 + * @see configureOptionsUsing */ public function configureReaderUsing(?callable $callback = null) { - $this->reader_configurator = $callback; - return $this; } @@ -175,39 +168,49 @@ public function configureReaderUsing(?callable $callback = null) * @param callable|null $callback * * @return $this + * + * @deprecated Has no effect with spout v4 + * @see configureOptionsUsing */ public function configureWriterUsing(?callable $callback = null) { - $this->writer_configurator = $callback; + return $this; + } + + /** + * Configure the underlying Spout Reader options using a callback. + * + * @param callable|null $callback + * + * @return $this + */ + public function configureOptionsUsing(?callable $callback = null) + { + $this->options_configurator = $callback; return $this; } /** - * @param \OpenSpout\Reader\ReaderInterface|\OpenSpout\Writer\WriterInterface $reader_or_writer + * @param AbstractOptions $options */ - protected function setOptions(&$reader_or_writer) + protected function setOptions(&$options) { - if ($reader_or_writer instanceof CsvReaderOptions || $reader_or_writer instanceof CsvWriterOptions) { - $reader_or_writer->FIELD_DELIMITER = $this->csv_configuration['delimiter']; - $reader_or_writer->FIELD_ENCLOSURE = $this->csv_configuration['enclosure']; - if ($reader_or_writer instanceof CsvReaderOptions) { - $reader_or_writer->ENCODING = $this->csv_configuration['encoding']; + if ($options instanceof CsvReaderOptions || $options instanceof CsvWriterOptions) { + $options->FIELD_DELIMITER = $this->csv_configuration['delimiter']; + $options->FIELD_ENCLOSURE = $this->csv_configuration['enclosure']; + if ($options instanceof CsvReaderOptions) { + $options->ENCODING = $this->csv_configuration['encoding']; } - if ($reader_or_writer instanceof CsvWriterOptions) { - $reader_or_writer->SHOULD_ADD_BOM = $this->csv_configuration['bom']; + if ($options instanceof CsvWriterOptions) { + $options->SHOULD_ADD_BOM = $this->csv_configuration['bom']; } } - if ($reader_or_writer instanceof ReaderInterface && is_callable($this->reader_configurator)) { - call_user_func( - $this->reader_configurator, - $reader_or_writer - ); - } elseif ($reader_or_writer instanceof WriterInterface && is_callable($this->writer_configurator)) { + if (is_callable($this->options_configurator)) { call_user_func( - $this->writer_configurator, - $reader_or_writer + $this->options_configurator, + $options ); } } diff --git a/src/Importable.php b/src/Importable.php index 7cc240e..fab9511 100644 --- a/src/Importable.php +++ b/src/Importable.php @@ -5,6 +5,7 @@ use Illuminate\Support\Collection; use Illuminate\Support\Str; use OpenSpout\Reader\SheetInterface; +use OpenSpout\Writer\Common\AbstractOptions; /** * Trait Importable. @@ -21,11 +22,11 @@ trait Importable private $sheet_number = 1; /** - * @param \OpenSpout\Reader\ReaderInterface|\OpenSpout\Writer\WriterInterface $reader_or_writer + * @param AbstractOptions $options * * @return mixed */ - abstract protected function setOptions(&$reader_or_writer); + abstract protected function setOptions(&$options); /** * @param string $path diff --git a/tests/FastExcelTest.php b/tests/FastExcelTest.php index 043f3ac..4372fdc 100644 --- a/tests/FastExcelTest.php +++ b/tests/FastExcelTest.php @@ -4,6 +4,7 @@ use OpenSpout\Common\Entity\Style\Color; use OpenSpout\Common\Entity\Style\Style; +use OpenSpout\Reader\XLSX\Options; use Rap2hpoutre\FastExcel\FastExcel; use Rap2hpoutre\FastExcel\SheetCollection; @@ -219,4 +220,33 @@ public function testExportWithHeaderStyle() unlink($file); } + + /** + * @throws \OpenSpout\Common\Exception\IOException + * @throws \OpenSpout\Common\Exception\UnsupportedTypeException + * @throws \OpenSpout\Reader\Exception\ReaderNotOpenedException + */ + public function testImportXlsxWithCustomDateOption() + { + // Default options, dates will end parsed + $collection = (new FastExcel())->import(__DIR__.'/test-dates.xlsx'); + + $this->assertEquals(collect([ + ['col1' => new \DateTimeImmutable('2022-01-02 00:00:00.000000')], + ['col1' => new \DateTimeImmutable('2022-01-03 00:00:00.000000')], + ]), $collection); + + $collection = (new FastExcel()) + ->configureOptionsUsing(function ($options) { + if ($options instanceof Options) { + $options->SHOULD_FORMAT_DATES = true; + } + }) + ->import(__DIR__.'/test-dates.xlsx'); + + $this->assertEquals(collect([ + ['col1' => '1/2/2022'], + ['col1' => '1/3/2022'], + ]), $collection); + } } diff --git a/tests/test-dates.xlsx b/tests/test-dates.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..fc4e2a40610fa6f6aa9523f710c29736da08f076 GIT binary patch literal 8701 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 A+5i9m literal 0 HcmV?d00001 From 6ed8898d8ecc0661a36d2d0831f5cd024ede7107 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Huchet?= Date: Fri, 1 Sep 2023 08:02:31 +0200 Subject: [PATCH 2/5] Apply fixes from StyleCI (#335) Co-authored-by: StyleCI Bot --- src/Exportable.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Exportable.php b/src/Exportable.php index 18ad4f2..e172e17 100644 --- a/src/Exportable.php +++ b/src/Exportable.php @@ -52,7 +52,7 @@ public function export($path, callable $callback = null) } /** - * @param $path + * @param $path * @param callable|null $callback * * @throws \OpenSpout\Common\Exception\InvalidArgumentException @@ -75,7 +75,7 @@ public function download($path, callable $callback = null) } /** - * @param $path + * @param $path * @param string $function * @param callable|null $callback * From 17e97d0d114bc56ec6e6279cf2e090af4dca1dfa Mon Sep 17 00:00:00 2001 From: Maher El Gamil Date: Fri, 1 Sep 2023 09:03:54 +0300 Subject: [PATCH 3/5] suport php8.1 (#316) --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 8600612..e23bc88 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ ], "description": "Fast Excel import/export for Laravel", "require": { - "php": "^8.0", + "php": "^8.0|^8.1", "illuminate/support": "^6.0 || ^7.0 || ^8.0 || ^9.0|^10.0", "openspout/openspout": "^4.1.1" }, From 97987c4f3d09e9ef8d9480b46116387e8bf6e3a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Huchet?= Date: Fri, 1 Sep 2023 08:07:32 +0200 Subject: [PATCH 4/5] chore: remove useless php version in composer --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index e23bc88..8600612 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ ], "description": "Fast Excel import/export for Laravel", "require": { - "php": "^8.0|^8.1", + "php": "^8.0", "illuminate/support": "^6.0 || ^7.0 || ^8.0 || ^9.0|^10.0", "openspout/openspout": "^4.1.1" }, From 45f8cb61a65564b05f59078cf0995f2559402901 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki Date: Fri, 1 Sep 2023 14:28:00 +0800 Subject: [PATCH 5/5] Attach `filename` to generate correct Content-Disposition header with PSR7 on Octane (#334) --- src/Exportable.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Exportable.php b/src/Exportable.php index e172e17..8b063ec 100644 --- a/src/Exportable.php +++ b/src/Exportable.php @@ -67,7 +67,7 @@ public function download($path, callable $callback = null) if (method_exists(response(), 'streamDownload')) { return response()->streamDownload(function () use ($path, $callback) { self::exportOrDownload($path, 'openToBrowser', $callback); - }); + }, $path); } self::exportOrDownload($path, 'openToBrowser', $callback);