Skip to content

Commit ec0d4af

Browse files
committed
AMORDEGRC and Csv Reader
Backports of PR #4162 and PR #4164 intended for 3.0.0.
1 parent 8edc294 commit ec0d4af

File tree

6 files changed

+66
-12
lines changed

6 files changed

+66
-12
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,19 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com)
66
and this project adheres to [Semantic Versioning](https://semver.org).
77

8+
## 1.29.2 - TBD
9+
10+
### Fixed
11+
12+
- Backported security patches.
13+
- Support for Php8.4.
14+
- Change to Csv Reader (see below under Deprecated). Backport of PR #4162 intended for 3.0.0. [Issue #4161](https://github.com/PHPOffice/PhpSpreadsheet/issues/4161)
15+
- Tweaks to ROUNDUP, ROUNDDOWN, TRUNC, AMORDEGRC (results had been different under 8.4).
16+
17+
### Deprecated
18+
19+
- Php8.4 will deprecate the escape parameter of fgetcsv. Csv Reader is affected by this; code is changed to be unaffected, but this will mean a breaking change is coming with Php9. Any code which uses the default escape value of backslash will fail in Php9. It is recommended to explicitly set the escape value to null string before then.
20+
821
## 1.29.1 - 2024-09-03
922

1023
### Fixed

src/PhpSpreadsheet/Calculation/Financial/Amortization.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99

1010
class Amortization
1111
{
12-
private const ROUNDING_ADJUSTMENT = (PHP_VERSION_ID < 80400) ? 0 : 1e-14;
13-
1412
/**
1513
* AMORDEGRC.
1614
*
@@ -82,7 +80,7 @@ public static function AMORDEGRC(
8280
$amortiseCoeff = self::getAmortizationCoefficient($rate);
8381

8482
$rate *= $amortiseCoeff;
85-
$rate += self::ROUNDING_ADJUSTMENT;
83+
$rate = (float) (string) $rate; // ugly way to avoid rounding problem
8684
$fNRate = round($yearFrac * $rate * $cost, 0);
8785
$cost -= $fNRate;
8886
$fRest = $cost - $salvage;

src/PhpSpreadsheet/Helper/Sample.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use PhpOffice\PhpSpreadsheet\Spreadsheet;
99
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
1010
use PhpOffice\PhpSpreadsheet\Writer\IWriter;
11+
use PhpOffice\PhpSpreadsheet\Writer\Pdf\Dompdf;
1112
use RecursiveDirectoryIterator;
1213
use RecursiveIteratorIterator;
1314
use RecursiveRegexIterator;
@@ -137,7 +138,11 @@ public function write(Spreadsheet $spreadsheet, $filename, array $writers = ['Xl
137138
$writerCallback($writer);
138139
}
139140
$callStartTime = microtime(true);
140-
$writer->save($path);
141+
if (PHP_VERSION_ID >= 80400 && $writer instanceof Dompdf) {
142+
@$writer->save($path);
143+
} else {
144+
$writer->save($path);
145+
}
141146
$this->logWrite($writer, $path, /** @scrutinizer ignore-type */ $callStartTime);
142147
if ($this->isCli() === false) {
143148
echo '<a href="/download.php?type=' . pathinfo($path, PATHINFO_EXTENSION) . '&name=' . basename($path) . '">Download ' . basename($path) . '</a><br />';

src/PhpSpreadsheet/Reader/Csv.php

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,17 @@ class Csv extends BaseReader
7575
/**
7676
* The character that can escape the enclosure.
7777
*
78-
* @var string
78+
* @var ?string
7979
*/
80-
private $escapeCharacter = '\\';
80+
private $escapeCharacter;
81+
82+
/**
83+
* The character that will be supplied to fgetcsv
84+
* when escapeCharacter is null.
85+
* It is anticipated that it will conditionally be set
86+
* to null-string for Php9 and above.
87+
*/
88+
private static string $defaultEscapeCharacter = '\\';
8189

8290
/**
8391
* Callback for setting defaults in construction.
@@ -198,7 +206,7 @@ protected function inferSeparator(): void
198206
return;
199207
}
200208

201-
$inferenceEngine = new Delimiter($this->fileHandle, $this->escapeCharacter, $this->enclosure);
209+
$inferenceEngine = new Delimiter($this->fileHandle, $this->escapeCharacter ?? self::$defaultEscapeCharacter, $this->enclosure);
202210

203211
// If number of lines is 0, nothing to infer : fall back to the default
204212
if ($inferenceEngine->linesCounted() === 0) {
@@ -529,6 +537,11 @@ public function getContiguous(): bool
529537
return $this->contiguous;
530538
}
531539

540+
/**
541+
* Php9 intends to drop support for this parameter in fgetcsv.
542+
* Not yet ready to mark deprecated in order to give users
543+
* a migration path.
544+
*/
532545
public function setEscapeCharacter(string $escapeCharacter): self
533546
{
534547
$this->escapeCharacter = $escapeCharacter;
@@ -538,7 +551,7 @@ public function setEscapeCharacter(string $escapeCharacter): self
538551

539552
public function getEscapeCharacter(): string
540553
{
541-
return $this->escapeCharacter;
554+
return $this->escapeCharacter ?? self::$defaultEscapeCharacter;
542555
}
543556

544557
/**
@@ -657,8 +670,9 @@ private static function getCsv(
657670
?int $length = null,
658671
string $separator = ',',
659672
string $enclosure = '"',
660-
string $escape = '\\'
673+
?string $escape = null
661674
) {
675+
$escape = $escape ?? self::$defaultEscapeCharacter;
662676
if (PHP_VERSION_ID >= 80400 && $escape !== '') {
663677
return @fgetcsv($stream, $length, $separator, $enclosure, $escape);
664678
}

tests/PhpSpreadsheetTests/Functional/StreamTest.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66
use PhpOffice\PhpSpreadsheet\Spreadsheet;
77
use PHPUnit\Framework\TestCase;
88

9+
/**
10+
* Not clear that Dompdf will be Php8.4 compatible in time.
11+
* Run in separate process and add version test till it is ready.
12+
*
13+
* @runTestsInSeparateProcesses
14+
*/
915
class StreamTest extends TestCase
1016
{
1117
public static function providerFormats(): array
@@ -40,7 +46,11 @@ public function testAllWritersCanWriteToStream(string $format): void
4046
} else {
4147
self::assertSame(0, $stat['size']);
4248

43-
$writer->save($stream);
49+
if ($format === 'Dompdf' && PHP_VERSION_ID >= 80400) {
50+
@$writer->save($stream);
51+
} else {
52+
$writer->save($stream);
53+
}
4454

4555
self::assertIsResource($stream, 'should not close the stream for further usage out of PhpSpreadsheet');
4656
$stat = fstat($stream);

tests/PhpSpreadsheetTests/Writer/Dompdf/PaperSizeArrayTest.php

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@
88
use PhpOffice\PhpSpreadsheet\Writer\Pdf\Dompdf;
99
use PHPUnit\Framework\TestCase;
1010

11+
/**
12+
* Not clear that Dompdf will be Php8.4 compatible in time.
13+
* Run in separate process and add version test till it is ready.
14+
*
15+
* @runTestsInSeparateProcesses
16+
*/
1117
class PaperSizeArrayTest extends TestCase
1218
{
1319
/** @var string */
@@ -35,7 +41,11 @@ public function testPaperSizeArray(): void
3541
$sheet->setCellValue('A7', 'Lorem Ipsum');
3642
$writer = new Dompdf($spreadsheet);
3743
$this->outfile = File::temporaryFilename();
38-
$writer->save($this->outfile);
44+
if (PHP_VERSION_ID >= 80400) { // hopefully temporary
45+
@$writer->save($this->outfile);
46+
} else {
47+
$writer->save($this->outfile);
48+
}
3949
$spreadsheet->disconnectWorksheets();
4050
unset($spreadsheet);
4151
$contents = file_get_contents($this->outfile);
@@ -55,7 +65,11 @@ public function testPaperSizeNotArray(): void
5565
$sheet->setCellValue('A7', 'Lorem Ipsum');
5666
$writer = new Dompdf($spreadsheet);
5767
$this->outfile = File::temporaryFilename();
58-
$writer->save($this->outfile);
68+
if (PHP_VERSION_ID >= 80400) { // hopefully temporary
69+
@$writer->save($this->outfile);
70+
} else {
71+
$writer->save($this->outfile);
72+
}
5973
$spreadsheet->disconnectWorksheets();
6074
unset($spreadsheet);
6175
$contents = file_get_contents($this->outfile);

0 commit comments

Comments
 (0)