Repository: PHPOffice/PhpSpreadsheet (php)

Issue:
$reader->setTestAutodetect() not usefull when php version > 8.1
This is:

```
- [x] a bug report
- [ ] a feature request
- [ ] **not** a usage question (ask them on https://stackoverflow.com/questions/tagged/phpspreadsheet or https://gitter.im/PHPOffice/PhpSpreadsheet)
```

### What is the expected behavior?
To not force the user to set autodetect to false when detected php version is >= 8.1
Simply keep it to false or never set it .


### What is the current behavior?
Forced to set false in order to not have problems with deprecation notices

### What are the steps to reproduce?

Set true with php >= 8.1 version

```php
<?php

require __DIR__ . '/vendor/autoload.php';

// Create new Spreadsheet object
$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();

// add code that show the issue here...
```
If this is an issue with reading a specific spreadsheet file, then it may be appropriate to provide a sample file that demonstrates the problem; but please keep it as small as possible, and sanitize any confidential information before uploading.

### What features do you think are causing the issue

- [ x] Reader
- [ ] Writer
- [ ] Styles
- [ ] Data Validations
- [ ] Formula Calculations
- [ ] Charts
- [ ] AutoFilter
- [ ] Form Elements

### Does an issue affect all spreadsheet file formats? If not, which formats are affected?
any software

### Which versions of PhpSpreadsheet and PHP are affected?
>= 8.1


Pull request description:
Breaking Change - 3 Defaults
Fix #4092. Change default value for Csv Reader autodetect line endings. Prior behavior can be enabled via `setTestAutodetect(true)`.

Change default value for Html Writer "better boolean" logic. Prior behavior can be explicitly enabled via `setBetterBoolean(false)`.

Change default for Xlsx Writer forceFullCalc option. Prior behavior can be explicitly enabled via `setForceFullCalc(null)`.

This is:

- [ ] a bugfix
- [ ] a new feature
- [ ] refactoring
- [ ] additional unit tests
- [x] more sensible default values

Checklist:

- [x] Changes are covered by unit tests
  - [x] Changes are covered by existing unit tests
  - [x] New unit tests have been added
- [x] Code style is respected
- [x] Commit message explains **why** the change is made (see https://github.com/erlang/otp/wiki/Writing-good-commit-messages)
- [x] CHANGELOG.md contains a short summary of the change and a link to the pull request if applicable
- [x] Documentation is updated as necessary


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 959648a02..adaa351e8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,9 @@ and this project adheres to [Semantic Versioning](https://semver.org).
 
 - Data Validations will be stored by worksheet, not cell. Index can be one or more cells or cell ranges. [Issue #797](https://github.com/PHPOffice/PhpSpreadsheet/issues/797) [Issue #4091](https://github.com/PHPOffice/PhpSpreadsheet/issues/4091) [Issue #4206](https://github.com/PHPOffice/PhpSpreadsheet/issues/4206) [PR #4240](https://github.com/PHPOffice/PhpSpreadsheet/pull/4240)
 - Conditional Formatting adds Priority property and handles overlapping ranges better. [Issue #4312](https://github.com/PHPOffice/PhpSpreadsheet/issues/4312) [Issue #4318](https://github.com/PHPOffice/PhpSpreadsheet/issues/4318) [PR #4314](https://github.com/PHPOffice/PhpSpreadsheet/pull/4314)
+- Csv Reader will no longer auto-detect Mac line endings by default. Prior behavior can be explicitly enabled via `setTestAutoDetect(true)`, and it will not be possible at all with Php9+. [Issue #4092](https://github.com/PHPOffice/PhpSpreadsheet/issues/4092) [PR #4340](https://github.com/PHPOffice/PhpSpreadsheet/pull/4340)
+- Html Writer will now use "better boolean" logic. Booleans will now be output by default as TRUE/FALSE rather than 1/null-string. Prior behavior can be explicitly enabled via `setBetterBoolean(false)`. [PR #4340](https://github.com/PHPOffice/PhpSpreadsheet/pull/4340)
+- Xlsx Writer will now use false as the default for `forceFullCalc`. This affects writes with `preCalculateFormulas` set to false. Prior behavior can be explicitly enabled via `setForceFullCalc(null)`.[PR #4340](https://github.com/PHPOffice/PhpSpreadsheet/pull/4340)
 - Deletion of items deprecated in Release 3. See "removed" below.
 
 ### Added
@@ -35,7 +38,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
 
 ### Fixed
 
-- Xls writer Parser Mishandling True/False Argument. [Issue #4331](https://github.com/PHPOffice/PhpSpreadsheet/issues/4331) [PR #4333](https://github.com/PHPOffice/PhpSpreadsheet/pull/4333)
+- Xls Writer Parser Mishandling True/False Argument. [Issue #4331](https://github.com/PHPOffice/PhpSpreadsheet/issues/4331) [PR #4333](https://github.com/PHPOffice/PhpSpreadsheet/pull/4333)
 
 ## 2025-01-26 - 3.9.0
 
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 709792031..88a03398f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -42,8 +42,8 @@ This makes it easier to see exactly what is being tested when reviewing the PR.
 3. Push the tag with `git push --tags`, GitHub Actions will create a GitHub release automatically, and the release details will automatically be sent to packagist.
 4. By default, Github removes markdown headings in the Release Notes. You can either edit to restore these, or, probably preferably, change the default comment character on your system - `git config core.commentChar ";"`.
 
-> **Note:** Tagged releases are made from the `master` branch. Only in an emergency should a tagged release be made from the `release` branch. (i.e. cherry-picked hot-fixes.) However, there are 3 branches which have been updated to apply security patches, and those may be tagged if future security updates are needed.
+> **Note:** Tagged releases are made from the `master` branch. Only in an emergency should a tagged release be made from the `release` branch. (i.e. cherry-picked hot-fixes.) However, there are 4 branches which have been updated to apply security patches, and those may be tagged if future security updates are needed.
 - release1291
 - release210
 - release222
-
+- release390
diff --git a/docs/topics/reading-and-writing-to-file.md b/docs/topics/reading-and-writing-to-file.md
index 28bc3b173..70946fcb5 100644
--- a/docs/topics/reading-and-writing-to-file.md
+++ b/docs/topics/reading-and-writing-to-file.md
@@ -173,7 +173,7 @@ even if pre-calculated is set to false
 ```php
 $writer->setForceFullCalc(false);
 ```
-In a future release, the property's default may change to `false` and that statement may no longer be required.
+Starting with Release 4.0.0, the property's default is changed to `false` and that statement is no longer be required. The property can be set to `null` if the old behavior is needed.
 
 #### Office 2003 compatibility pack
 
@@ -594,6 +594,9 @@ You can suppress testing for Mac line endings as follows:
 $reader = new \PhpOffice\PhpSpreadsheet\Reader\Csv();
 $reader->setTestAutoDetect(false);
 ```
+Starting with Release 4.0.0, the property defaults to `false`,
+so the statement above is no longer needed. The old behavior
+can be enabled by setting the property to `true`.
 
 ### \PhpOffice\PhpSpreadsheet\Writer\Csv
 
diff --git a/src/PhpSpreadsheet/Reader/Csv.php b/src/PhpSpreadsheet/Reader/Csv.php
index 89cbfd5ad..9455993e8 100644
--- a/src/PhpSpreadsheet/Reader/Csv.php
+++ b/src/PhpSpreadsheet/Reader/Csv.php
@@ -84,8 +84,8 @@ class Csv extends BaseReader
      */
     private static $constructorCallback;
 
-    /** Will be changed to false in next major release */
-    public const DEFAULT_TEST_AUTODETECT = true;
+    /** Changed from true to false in release 4.0.0 */
+    public const DEFAULT_TEST_AUTODETECT = false;
 
     /**
      * Attempt autodetect line endings (deprecated after PHP8.1)?
diff --git a/src/PhpSpreadsheet/Writer/Html.php b/src/PhpSpreadsheet/Writer/Html.php
index 2b1d0a474..83c99983e 100644
--- a/src/PhpSpreadsheet/Writer/Html.php
+++ b/src/PhpSpreadsheet/Writer/Html.php
@@ -143,7 +143,7 @@ class Html extends BaseWriter
     /** @var Chart[] */
     private $sheetCharts;
 
-    private bool $betterBoolean = false;
+    private bool $betterBoolean = true;
 
     private string $getTrue = 'TRUE';
 
@@ -1494,7 +1494,7 @@ class Html extends BaseWriter
             $dataType = $worksheet->getCell($coordinate)->getDataType();
             if ($dataType === DataType::TYPE_BOOL) {
                 $html .= ' data-type="' . DataType::TYPE_BOOL . '"';
-            } elseif ($dataType === DataType::TYPE_FORMULA && is_bool($worksheet->getCell($coordinate)->getCalculatedValue())) {
+            } elseif ($dataType === DataType::TYPE_FORMULA && $this->preCalculateFormulas && is_bool($worksheet->getCell($coordinate)->getCalculatedValue())) {
                 $html .= ' data-type="' . DataType::TYPE_BOOL . '"';
             } elseif (is_numeric($cellData) && $worksheet->getCell($coordinate)->getDataType() === DataType::TYPE_STRING) {
                 $html .= ' data-type="' . DataType::TYPE_STRING . '"';
diff --git a/src/PhpSpreadsheet/Writer/Xlsx.php b/src/PhpSpreadsheet/Writer/Xlsx.php
index b74d81050..c2fbd0cbc 100644
--- a/src/PhpSpreadsheet/Writer/Xlsx.php
+++ b/src/PhpSpreadsheet/Writer/Xlsx.php
@@ -140,7 +140,10 @@ class Xlsx extends BaseWriter
 
     private bool $useDynamicArray = false;
 
-    private ?bool $forceFullCalc = null;
+    public const DEFAULT_FORCE_FULL_CALC = false;
+
+    // Default changed from null in PhpSpreadsheet 4.0.0.
+    private ?bool $forceFullCalc = self::DEFAULT_FORCE_FULL_CALC;
 
     /**
      * Create a new Xlsx Writer.
@@ -758,6 +761,7 @@ class Xlsx extends BaseWriter
      * If null, this will be set to the opposite of $preCalculateFormulas.
      * It is likely that false is the desired setting, although
      * cases have been reported where true is required (issue #456).
+     * Nevertheless, default is set to false in PhpSpreadsheet 4.0.0.
      */
     public function setForceFullCalc(?bool $forceFullCalc): self
     {


Test patch:
diff --git a/tests/PhpSpreadsheetTests/Reader/Csv/CsvLineEndingTest.php b/tests/PhpSpreadsheetTests/Reader/Csv/CsvLineEndingTest.php
index 3fc1d3031..51ead8bdb 100644
--- a/tests/PhpSpreadsheetTests/Reader/Csv/CsvLineEndingTest.php
+++ b/tests/PhpSpreadsheetTests/Reader/Csv/CsvLineEndingTest.php
@@ -6,6 +6,7 @@ namespace PhpOffice\PhpSpreadsheetTests\Reader\Csv;
 
 use PhpOffice\PhpSpreadsheet\Reader\Csv;
 use PhpOffice\PhpSpreadsheet\Shared\File;
+use PHPUnit\Framework\Attributes\DataProvider;
 use PHPUnit\Framework\TestCase;
 
 class CsvLineEndingTest extends TestCase
@@ -22,7 +23,7 @@ class CsvLineEndingTest extends TestCase
         }
     }
 
-    #[\PHPUnit\Framework\Attributes\DataProvider('providerEndings')]
+    #[DataProvider('providerEndings')]
     public function testEndings(string $ending): void
     {
         if ($ending === "\r" && PHP_VERSION_ID >= 90000) {
@@ -43,14 +44,14 @@ class CsvLineEndingTest extends TestCase
         $spreadsheet->disconnectWorksheets();
     }
 
-    #[\PHPUnit\Framework\Attributes\DataProvider('providerEndings')]
+    #[DataProvider('providerEndings')]
     public function testEndingsNoDetect(string $ending): void
     {
         $this->tempFile = $filename = File::temporaryFilename();
         $data = ['123', '456', '789'];
         file_put_contents($filename, implode($ending, $data));
         $reader = new Csv();
-        $reader->setTestAutoDetect(false);
+        self::assertSame(self::$alwaysFalse, Csv::DEFAULT_TEST_AUTODETECT);
         $spreadsheet = $reader->load($filename);
         $sheet = $spreadsheet->getActiveSheet();
         if ($ending === "\r") {
diff --git a/tests/PhpSpreadsheetTests/Reader/Xlsx/Issue4248Test.php b/tests/PhpSpreadsheetTests/Reader/Xlsx/Issue4248Test.php
index de5ec8f02..4fd45c395 100644
--- a/tests/PhpSpreadsheetTests/Reader/Xlsx/Issue4248Test.php
+++ b/tests/PhpSpreadsheetTests/Reader/Xlsx/Issue4248Test.php
@@ -94,7 +94,7 @@ class Issue4248Test extends TestCase
             . '            <td class="column0 style0">&nbsp;</td>'
             . '            <td class="column1 style28 null"></td>'
             . '            <td class="column2 style35 s">Eligible </td>'
-            . '            <td class="column3 style70 f">Non</td>';
+            . '            <td class="column3 style70 s">Non</td>';
         self::assertStringContainsString($expected, $data, 'Cell D18 style');
         $expected = '      td.style70, th.style70 { vertical-align:middle; text-align:center; border-bottom:1px solid #000000 !important; border-top:2px solid #000000 !important; border-left:2px solid #000000 !important; border-right:1px solid #000000 !important; font-weight:bold; color:#000000; font-family:\'Calibri\'; font-size:16pt; background-color:#BDD7EE }';
         self::assertStringContainsString($expected, $data, 'background color');
diff --git a/tests/PhpSpreadsheetTests/Writer/Html/BadHyperlinkTest.php b/tests/PhpSpreadsheetTests/Writer/Html/BadHyperlinkTest.php
index 6e2634c6c..63cc4d89c 100644
--- a/tests/PhpSpreadsheetTests/Writer/Html/BadHyperlinkTest.php
+++ b/tests/PhpSpreadsheetTests/Writer/Html/BadHyperlinkTest.php
@@ -18,7 +18,7 @@ class BadHyperlinkTest extends TestCase
         $spreadsheet = $reader->load($infile);
         $writer = new HtmlWriter($spreadsheet);
         $html = $writer->generateHtmlAll();
-        self::assertStringContainsString('<td class="column0 style1 f">jav&#9;ascript:alert()</td>', $html);
+        self::assertStringContainsString('<td class="column0 style1 s">jav&#9;ascript:alert()</td>', $html);
         $spreadsheet->disconnectWorksheets();
     }
 
@@ -29,7 +29,7 @@ class BadHyperlinkTest extends TestCase
         $spreadsheet = $reader->load($infile);
         $writer = new HtmlWriter($spreadsheet);
         $html = $writer->generateHtmlAll();
-        self::assertStringContainsString('<td class="column0 style0 f">&#20;j&#13;avascript:alert(1)</td>', $html);
+        self::assertStringContainsString('<td class="column0 style0 s">&#20;j&#13;avascript:alert(1)</td>', $html);
         $spreadsheet->disconnectWorksheets();
     }
 }
diff --git a/tests/PhpSpreadsheetTests/Writer/Html/BetterBooleanTest.php b/tests/PhpSpreadsheetTests/Writer/Html/BetterBooleanTest.php
index 0eac757d4..71d81122a 100644
--- a/tests/PhpSpreadsheetTests/Writer/Html/BetterBooleanTest.php
+++ b/tests/PhpSpreadsheetTests/Writer/Html/BetterBooleanTest.php
@@ -31,8 +31,8 @@ class BetterBooleanTest extends Functional\AbstractFunctional
     {
         $spreadsheet = new Spreadsheet();
         $writer = new HtmlWriter($spreadsheet);
-        // Default will change with next PhpSpreadsheet release
-        self::assertFalse($writer->getBetterBoolean());
+        // Default change with release 4.0.0
+        self::assertTrue($writer->getBetterBoolean());
         $spreadsheet->disconnectWorksheets();
     }
 
@@ -58,9 +58,7 @@ class BetterBooleanTest extends Functional\AbstractFunctional
         $sheet->getCell('F1')->setValue('="A"&"B"');
         $sheet->getCell('G1')->setValue('=1+2');
 
-        /** @var callable */
-        $callableWriter = [$this, 'setBetter'];
-        $reloaded = $this->writeAndReload($spreadsheet, 'Html', null, $callableWriter);
+        $reloaded = $this->writeAndReload($spreadsheet, 'Html');
         $spreadsheet->disconnectWorksheets();
 
         $rsheet = $reloaded->getActiveSheet();
@@ -86,9 +84,7 @@ class BetterBooleanTest extends Functional\AbstractFunctional
         $sheet->getCell('F1')->setValue('="A"&"B"');
         $sheet->getCell('G1')->setValue('=1+2');
 
-        /** @var callable */
-        $callableWriter = [$this, 'setNotBetter'];
-        $reloaded = $this->writeAndReload($spreadsheet, 'Html', null, $callableWriter);
+        $reloaded = $this->writeAndReload($spreadsheet, 'Html', null, $this->setNotBetter(...));
         $spreadsheet->disconnectWorksheets();
 
         $rsheet = $reloaded->getActiveSheet();
@@ -125,9 +121,7 @@ class BetterBooleanTest extends Functional\AbstractFunctional
         self::assertStringContainsString('<td class="column5 style0 s">AB</td>', $html);
         self::assertStringContainsString('<td class="column6 style0 n">3</td>', $html);
 
-        /** @var callable */
-        $callableWriter = [$this, 'setBetter'];
-        $reloaded = $this->writeAndReload($spreadsheet, 'Html', null, $callableWriter);
+        $reloaded = $this->writeAndReload($spreadsheet, 'Html', null, $this->setBetter(...));
         $spreadsheet->disconnectWorksheets();
 
         $rsheet = $reloaded->getActiveSheet();
@@ -169,9 +163,7 @@ class BetterBooleanTest extends Functional\AbstractFunctional
         self::assertStringContainsString('<td style="text-align:left;">AB</td>', $html);
         self::assertStringContainsString('<td style="text-align:right;">3</td>', $html);
 
-        /** @var callable */
-        $callableWriter = [$this, 'setBetter'];
-        $reloaded = $this->writeAndReload($spreadsheet, 'Html', null, $callableWriter);
+        $reloaded = $this->writeAndReload($spreadsheet, 'Html', null, $this->setBetter(...));
         $spreadsheet->disconnectWorksheets();
 
         $rsheet = $reloaded->getActiveSheet();
diff --git a/tests/PhpSpreadsheetTests/Writer/Html/NoJavascriptLinksTest.php b/tests/PhpSpreadsheetTests/Writer/Html/NoJavascriptLinksTest.php
index cc0511d4f..156f9079d 100644
--- a/tests/PhpSpreadsheetTests/Writer/Html/NoJavascriptLinksTest.php
+++ b/tests/PhpSpreadsheetTests/Writer/Html/NoJavascriptLinksTest.php
@@ -27,7 +27,7 @@ class NoJavascriptLinksTest extends TestCase
         $html = $writer->generateHTMLAll();
         self::assertStringContainsString('<td class="column0 style0 s"><a href="http://www.example.com">Click me</a></td>', $html, 'http hyperlink retained');
         self::assertStringContainsString('<td class="column0 style0 s">javascript:alert(\'hello1\')</td>', $html, 'javascript hyperlink dropped');
-        self::assertStringContainsString('<td class="column0 style0 f">javascript:alert(\'hello2\')</td>', $html, 'javascript hyperlink function dropped');
+        self::assertStringContainsString('<td class="column0 style0 s">javascript:alert(\'hello2\')</td>', $html, 'javascript hyperlink function dropped');
         $spreadsheet->disconnectWorksheets();
     }
 }
diff --git a/tests/PhpSpreadsheetTests/Writer/PreCalcTest.php b/tests/PhpSpreadsheetTests/Writer/PreCalcTest.php
index eb9530bde..818070171 100644
--- a/tests/PhpSpreadsheetTests/Writer/PreCalcTest.php
+++ b/tests/PhpSpreadsheetTests/Writer/PreCalcTest.php
@@ -10,6 +10,7 @@ use PhpOffice\PhpSpreadsheet\Shared\File;
 use PhpOffice\PhpSpreadsheet\Spreadsheet;
 use PhpOffice\PhpSpreadsheet\Worksheet\ColumnDimension;
 use PhpOffice\PhpSpreadsheetTests\Functional\AbstractFunctional;
+use PHPUnit\Framework\Attributes\DataProvider;
 
 class PreCalcTest extends AbstractFunctional
 {
@@ -117,7 +118,7 @@ class PreCalcTest extends AbstractFunctional
             $data = self::readFile($file);
             // confirm whether workbook is set to recalculate
             if ($preCalc === false) {
-                self::assertStringContainsString('<calcPr calcId="999999" calcMode="auto" calcCompleted="0" fullCalcOnLoad="1" forceFullCalc="1"/>', $data);
+                self::assertStringContainsString('<calcPr calcId="999999" calcMode="auto" calcCompleted="0" fullCalcOnLoad="1" forceFullCalc="0"/>', $data);
             } else {
                 self::assertStringContainsString('<calcPr calcId="999999" calcMode="auto" calcCompleted="1" fullCalcOnLoad="0" forceFullCalc="0"/>', $data);
             }
@@ -174,7 +175,7 @@ class PreCalcTest extends AbstractFunctional
         }
     }
 
-    #[\PHPUnit\Framework\Attributes\DataProvider('providerPreCalc')]
+    #[DataProvider('providerPreCalc')]
     public function testPreCalc(?bool $preCalc, string $type): void
     {
         $spreadsheet = new Spreadsheet();
@@ -203,5 +204,6 @@ class PreCalcTest extends AbstractFunctional
         $this->verifyOds($preCalc, $type);
         $this->verifyHtml($preCalc, $type);
         $this->verifyCsv($preCalc, $type);
+        $spreadsheet->disconnectWorksheets();
     }
 }
diff --git a/tests/PhpSpreadsheetTests/Writer/Xlsx/Issue4269Test.php b/tests/PhpSpreadsheetTests/Writer/Xlsx/Issue4269Test.php
index ffe9e30ae..b78a9394b 100644
--- a/tests/PhpSpreadsheetTests/Writer/Xlsx/Issue4269Test.php
+++ b/tests/PhpSpreadsheetTests/Writer/Xlsx/Issue4269Test.php
@@ -14,6 +14,8 @@ class Issue4269Test extends TestCase
 {
     private string $outputFile = '';
 
+    private static bool $alwaysFalse = false;
+
     protected function tearDown(): void
     {
         if ($this->outputFile !== '') {
@@ -35,9 +37,7 @@ class Issue4269Test extends TestCase
 
         $writer = new XlsxWriter($spreadsheet);
         $writer->setPreCalculateFormulas($preCalculateFormulas);
-        if ($forceFullCalc !== null) {
-            $writer->setForceFullCalc($forceFullCalc);
-        }
+        $writer->setForceFullCalc($forceFullCalc);
         $this->outputFile = File::temporaryFilename();
         $writer->save($this->outputFile);
         $spreadsheet->disconnectWorksheets();
@@ -62,4 +62,9 @@ class Issue4269Test extends TestCase
             'unlikely use case' => [true, true, 'calcMode="auto" calcCompleted="1" fullCalcOnLoad="0" forceFullCalc="1"'],
         ];
     }
+
+    public function testDefault(): void
+    {
+        self::assertSame(self::$alwaysFalse, XlsxWriter::DEFAULT_FORCE_FULL_CALC);
+    }
 }