* PhpUnit 10 Compatibility Part 3 (Last)
Final changes for PhpUnit 10, including enabling it for testing. This finishes the work of PR #3523 and PR #3526.
The major remaining problem with PhpUnit 10 is that earlier releases converted notices and warnings to exceptions, and 10 does not. Not having the information provided by the messages seems risky to me. Fortunately, it appears that you can add an error handler to the test bootstrap for 10 and make it act like earlier versions; I have done so. In order to demonstrate the effectiveness of this handler, a new otherwise unused class Helper/Handler and tests for that class are added.
As part of the testing of this change, it became apparent that the fopen in OLE::getStream attempts to create a dynamic property $context in Shared/OLE/ChainedBlockStream, and that action is deprecated in Php8.2. Adding the property to the class eliminates that problem. No executable code is added, and this is the only change to source code.
There also seems to have been a change in assertXmlStringEqualsXmlString in PhpUnit 10. The only test which uses that method is Chart/Issue589Test, and both the places which use that method could just as easily and effectively use assertSame. They are changed to do so.
* Remove Phpunit Verbose Option
Not supported in PhpUnit 10. I'm not at all sure that this is the correct solution for this problem.
* Try Changing Phpunit Command for Different Php Releases
Not sure how to test this locally. We'll see if it works on github.
* Another main.yml attempt
We shall see.
* Eliminate One Test
Not sure why testDeprecated is not working in Github; it works locally. Disable it for now and continue to research.
* Show Incomplete and Other Messages in PhpUnit 10
6 new command line args to replace the 1 they got rid of.
* Restore Disabled Test
Deprecated messages are suppressed by default setting for error_reporting. Switch that to E_ALL in bootstrap and restore original test.
* Add Deprecation Tests for PhpUnit 9-
Default configuration option caused deprecation messages to be suppressed. Change the option.
Successor to PR #3523. There are 494 single-line changes (`public function provider` to `public static function provider`) in this PR. None of these were made manually; they were all created with the following script (adapted from
https://stackoverflow.com/questions/25909820/how-to-recursively-iterate-through-files-in-php):
```php
$dir = 'C:/git/unit10prep2/tests/PhpSpreadsheetTests';
$it = new RecursiveDirectoryIterator($dir);
// Loop through files
foreach(new RecursiveIteratorIterator($it) as $file) {
if ($file->getExtension() === 'php') {
$contents = file_get_contents($file);
$new = preg_replace('/public function (\\w*)([Pp])rovider/', 'public static function $1$2rovider', $contents);
if ($new !== $contents) {
echo "changing $file\n";
file_put_contents($file, $new);
}
}
}
```
After this PR, there will be one more, with a small number of test changes, and enabling PhpUnit 10 for Php 8.1+.
* PhpUnit 10 Compatibility Part 1
This is not a change to move to PhpUnit 10. There is no compelling reason to do so at this time, although it is bound to happen eventually. There are a staggering number of problems (somewhere around 3,000) with the current test suite under PhpUnit 10; this is an attempt to get ahead of the curve by addressing them now.
Method `setOutputCallback` has gone away. This affects only Helper/SampleTest. It appears that `ob_start` and its allies provide an effective equivalent. FWIW, the absence of `setOutputCallback` is a good indication of whether or not PhpUnit 10 is in use, and I will use that fact in a few tests.
Class `ComplexAssert` with no constructor, and always used with `new ComplexAssert()`, extends `TestCase`. Apparently, the constructor for TestCase requires an argument, and PhpUnit 10 complains about not supplying one. Adding an empty constructor to ComplexAssert avoids this problem.
There are two very minor source changes, to Calculation/Calculation and Reader/Xlsx, where problems were exposed with PhpUnit 10 that had not been previously been exposed. AFAIK, these are the only source changes required; the rest of the changes are to test members.
The bulk of the problems are because PhpUnit 10 insists that provider methods be static. Most of those can be changed by a script without any further action; those changes will constitute the Part 2 counterpart of this PR. In this PR you will find the exceptional cases that can't be automated for one reason or another. The tests for Database functions have mild complications that are easily handled. Most of the other provider changes in this PR are because the method names didn't follow an established pattern ('provider' isn't part of the method name); those are also easily handled manually. Modifying the following tests provided significant challenges:
- Writer/Xls/WorkbookTest testAddColor
- Worksheet/Table/TableTest testSetRangeValidRange
The handling of warning messages issued by the code differs in PhpUnit 10. According to the change log, "This means that using PHP functionality which triggers E_DEPRECATED, E_NOTICE, E_STRICT, or E_WARNING or calling code which triggers E_USER_DEPRECATED, E_USER_NOTICE, or E_USER_WARNING can no longer hide a bug in your code." To me, the effect of that change seems to be exactly the opposite - such messages were available to the test with PhpUnit 9 (so we could test for them), and are no longer available (so we can't). I haven't even succeeded with a custom error message handler as part of the script. I will continue to investigate, but, for now, will skip some tests under PhpUnit 10 for the following:
- Shared/OleTest testChainedWriteMode and testChainedBadPath
- Reader/Html/HtmlLoadStringTest testLoadInvalidString
- Reader/Html/HtmlTest testBadHtml
* Scrutinize, and Parent Construct
Parent construct suggested by @MarkBaker.
* Redo Tests Dependent on Warning Messages
Warning (and other) messages are handled differently in PhpUnit 10 than in earlier versions.
Stock charts currently ignore upDownBars tag and its subsidiary gapWidth, upBars, and downBars tags when reading, and hard-codes those tags on write. As a result, the sample reproductions of stock charts in the 32* series aren't faithful to the originals. This PR fixes samples 1, 2, and 5. Samples 3 and 4 are reproduced better, but they require currently unsupported secondary axes (issue #560, issue #1072, and PR #1073 were closed as stale; see also https://github.com/PHPOffice/PHPExcel/pull/1037). I will start to look at those, but it could take a while, and I don't think there's a reason to delay this in the meantime.
Charts which depended on the hard-coded values written by the Xlsx Chart writer will be slightly different as a result of this change. To restore the hard-coded behavior:
```php
$plotArea->setGapWidth(300);
$plotArea->setUseUpBars(true);
$plotArea->setUseDownBars(true);
```
The new behavior is demonstrated in 33_Chart_create_stock. The old behavior is demonstrated (with the code above) in new 33_Chart_create_stock2.
Wanting a sanity test for ExactFontTest, I used the MD5 of a known file. However, there are various versions of the file in the wild, and use of these variants cause test to be skipped. Allow known variations to satisfy MD5 check.
* Add Ability to Ignore Cell Errors in Excel
Fix#1141, which had been closed as stale, but which I have reopened. Excel will show cells with certain "errors" with a green triangle in the upper left. The suggestion in the issue to use quotePrefix to suppress the numberStoredAsText error is ineffective. In Excel, the user can turn this indicator off for individual cells. Cells where this is turned off can be detected at read time, and PhpSpreadsheet will now process those. In addition, the user can explicitly set the ignored error as in Excel.
```php
$cell->setIgnoredErrorNumberStoredAsText(true);
```
There are a number of different errors that can be ignored in this fashion. This PR implements `numberStoredAsText` (which is likely to be by far the most useful one), `formula`, `twoDigitTextYear`, and `evalError`, all of which are demonstrated in the new test spreadsheet. There are several others for which I am not able to create good examples; I have not implemented those, but they can be easily added if needed (`calculatedColumn`, `emptyCellReference`, `formulaRange`, `listDataValidation`, and `unlockedFormula`).
* Scrutinizer
A new change, a new Scrutinizer false positive.
* Move Ignored Errors to Own Class
In response to comments from @MarkBaker, implement ignoredError as a new class. This simplifies Cell by requiring only 1 new method, rather than 8+. This requires a slightly more complicated syntax.
```php
$cell->getIgnoredErrors()->setNumberScoredAsText(true);
```
Mark had also suggested that there might be a pre-existing regexp for processing the cells/cellranges when reading the sqref attribute. Those in Calculation are too complicated (read "non-performant") for this piece of code; the one in Coordinates is slightly less complicated than Calculation, but still more complicated than the one I'm using, and doesn't handle ranges.
Fix#3495. This seems to be a bug in Excel, one which it manages to cover up but PhpSpreadsheet is affected. User enters a formula preceded by an apostrophe into a cell. Excel turns on `quotePrefix` style and stores the data as a string rather than a formula. User now enters a formula not preceded by an apostrophe into the same cell. Excel stores it is a formula but does not turn `quotePrefix` off. When the spreadsheet is saved, the cell's style specifies `quotePrefix`, but the cell's content indicates it's a formula. Till now, PhpSpreadsheet sees that quotePrefix is set, and therefore treats the cell's contents as a string rather than a formula. This PR will change that behavior so that quotePrefix is automatically turned off when Xlsx Reader sees that the cell indicates that it is a formula.
* Font Themes
It isn't a feature of Excel that I've made any use of, but PR #3476 added better Theme support for colors, and it is relatively easy to add Theme support for Fonts on top of that.
Excel assigns two theme fonts to its spreadsheets, one for Headings (major), and one for Body (minor). If the body theme is Calibri, when you choose a font for a cell in Excel, you can choose 'Calibri (Body)' from the Theme Fonts section at the top of the Font dropdown, or 'Calibri' from the 'All Fonts' section. If you choose the former, the cell will be automatically restyled if you change the Theme Fonts (via Page Layout, Themes, Fonts). The relationship to the theme fonts is recorded in the XML via a `scheme` tag (descending from `font`) whose `val` attribute can be either `major` or `minor`. Accordingly, this PR, in addition to defining the Theme Font properties, adds a `scheme` property, with getter and setter, to Style/Font.
The main benefit of this PR is that you can now load and save a spreadsheet preserving the connections to the Theme Fonts, without having to take any additional action.
A secondary benefit arises from the following difference. Empty cells in Excel will use the spreadsheet's default font name when they are filled in; but, in Google Sheets, they will use the Theme Minor Font name. By setting the `scheme` property in the default style, the resulting spreadsheet will behave the same in both Excel and Google.
I will note that Excel's font themes specify a Latin font, an East Asian font, a Complex Scripts font, and a set of font substitutions for various languages. PhpSpreadsheet will preserve all of these, and allow them to be changed. However, although it is easy to imagine how the non-Latin options might work, I have not yet been able to come up with an example where Excel uses any of them. In particular, if I use a theme font which does not support language X, and I use Language X in a cell bound to the theme, Excel will use a substitution font which does support it, but the font which it uses does not seem to be chosen from the alternatives supplied in the theme.
* Scrutinizer
The sun rises in the east, and Scrutinizer issues more false positives.