Commit Graph

93 Commits

Author SHA1 Message Date
Mark Baker 6b746dc05f
Extract some methods from the Calculation Engine into dedicated classes (#2537)
* Move binary comparisons out into a dedicated class
2022-02-04 16:02:29 +01:00
Mark Baker 4a04499bff
Read conditional styling for cell (#2491)
* Allow single-cell checks on conditional styles, even when the style is configured for a range of cells
* Work on the CellMatcher logic to evaluate Conditionals for a cell based on its value, and identify which conditional styles should be applied
* Refactor style merging and cell matching for conditional formatting into separate classes; this should make it easier to test, and easier to extend for other CF expressions subsequently
* Added support for containsErrors and notContainsErrors
* Initial work on a wizard to help simplify created Conditional Formatting rules, to ensure that the correct expressions are set
* Further work on extending the Conditional Formatting rules to cover more of the options that are available in MS Excel
* Prevent phpcs-fixer from removing class @method annotations, used to identify the signature for magic methods used in Wizard classes
* Implement `fromConditional()`` method to allow the creation of a CF Wizard from an existing Conditional
* Ensure that xlsx Reader picks up the timePeriod attribute for DatesOccurring CF Rules
* Allow Duplicates/Uniques CF Rules to be recognised in the Xlsx Reader
* Basic Xlsx reading of CF Rules/Styles from <extLst><ext><ConditinalFormattings> element, and not just the <ConditinalFormatting> element of the worksheet

* Add some validation for operands passed to the CF Wizards
 - remove any leading ``=` from formulae, because they'll be embedded into other formulae
 - unwrap any string literals from quotes, because that's also handled internally

Handle cross-worksheet cell references in cellReferences and Formulae/Expressions

* re-baseline phpstan

* Update Change Log with details of the CF Improvements
2022-01-22 19:18:26 +01:00
oleibman 95d9cc965d
Refinement for XIRR (#2487)
* Refinement for XIRR

Fix #2469. The algorithm used for XIRR is known not to converge in some cases, some of which are because the value is legitimately unsolvable; for others, using a different guess might help.

The algorithm uses continual guesses at a rate to hopefully converge on the solution. The code in Python package xirr (https://github.com/tarioch/xirr/) suggests a refinement when this rate falls below -1. Adopting this refinement solves the problem for the data in issue 2469 without any adverse effect on the existing tests. My thanks to @tarioch for that refinement.

The data from 2469 is, of course, added to the test cases. The user also mentions that an initial guess equal to the actual result doesn't converge either. A test is also added to confirm that that case now works.

The test cases are changed to run in the context of a spreadsheet rather than by direct calls to XIRR calculation routine. This revealed some data validation errors which are also cleaned up with this PR. This suggests that other financial tests might benefit from the same change; I will look into that.

* More Unit Tests

From https://github.com/RayDeCampo/java-xirr/blob/master/src/test/java/org/decampo/xirr/XirrTest.java
https://github.com/tarioch/xirr/blob/master/tests/test_math.py

Note that there are some cases where the PHP tests do not converge, but the non-PHP tests do. I have confirmed in each of those cases that Excel does not converge, so the PhpSpreadsheet results are good, at least for now. The discrepancies are noted in comments in the test member.
2022-01-13 19:31:46 -08:00
oleibman 7d71a7ca54
New Error Reported with Phpstan 1.3 (#2481)
* New Error Reported with Phpstan 1.3

Dependabot opened a number of PRs. Most are successful, but this change is necessary to allow PR #2477 to complete successfully, and that is apparently a necessity for PR #2479.

Phpstan 1.3 objected to:
```php
trigger_error($errorMessage, E_USER_ERROR);
return false;
```
It claims the return statement is unreachable. This isn't precisely true - an error handler might allow the return to be reached. At any rate, I have slightly restructured the code so that Phpstan will not object either with 1.2 or 1.3, which should allow the blocked PRs to succeed. There had been no previous tests for what happens when there is a formula error when suppressFormulaErrors is true.

* Scrutinizer

Didn't like effect of changes which Phpstan liked. Hopefully this will work better.

* Improvement

Eliminate added function.
2022-01-03 17:32:52 -08:00
oleibman 5d1ab39def
Replace Tests With Unneeded Mocking (#2465)
Replace mock tests with real ones when possible. The original tests are all still present; they just take place in a more representative scenario.

After this, there will be 4 remaining uses of mocking. Of these, 3 are needed for scenarios which are otherwise hard to test - WebServiceTest, CellsTest, and SampleCoverageTest. For the other one, AutoFilterTest, I just can't figure out what it's trying to accomplish, so have left it alone.

This change is almost entirely restricted to tests. There is a one-line change in src. When the first argument passed to OFFSET is null or nullstring, the returned value is currently 0. However, according to the documentation for Excel, it should be `#VALUE!`. The code is changed accordingly.
2021-12-31 13:24:43 -08:00
oleibman 07271c83aa
Rename Two Test Files (#2459)
* Rename Two Test Files

When I run unit tests only for Reader/Xlsx, phpunit is issuing a deprecation message because the names of 2 files have an extra dot in them and thus don't match the class name in the file. I do not see these warnings when I run the entire test suite.

* Remove Phpstan Annotations

It was a bit difficult to handle a cast from mixed to string.

* Fix Same Phpstan Problem in One Other Test

This is the only other test case that tries to cast mixed to string.
2021-12-25 09:05:54 -08:00
oleibman f2b2f07ec3
Null Passed to AutoFilter SetRange (#2454)
* Null Passed to AutoFilter SetRange

Fix #2281. Delete auto filter set range to null, but should set it to null string. This causes a deprecation warning in Php8.1.

* Constructor Call Also Sets Range to Null

Should set it to null string.
2021-12-25 08:45:10 -08:00
oleibman 67bf45d700
Fill Pattern Start and End Colors (#2444)
* Fill Pattern Start and End Colors

Fix #2441. The Fill constructor sets start color to white and end color to black and the Xlsx writer writes these values to the output file. This appears to be the wrong setting for all 7 LIGHT* pattern types, 2 of the 7 DARK* patterns (DARKGRAY and DARKTRELLIS), and 1 of the 3 GRAY patterns (GRAY0625). When the wrong colors are written at save time, those patterns are not as expected. Xls writer does not appear to have the same problem.

The XML does not require either a start or end color, and the omission of these colors in the file being read was responsible for the problem. The code is changed to mimic that behavior by omitting the color tags at write time if they have not changed from when they were created by the Fill constructor (they will be written for gradient or solid patterns regardless).

This is another change which is easier to confirm via samples rather than tests. There are separate samples for Xlsx and Xls; as Excel will be quick to warn you, Xls is not as fully functional as Xlsx with respect to fill patterns. The samples do include a cell where one of the cells (LightGrid in C11) explicitly specifies the "default" colors.

* Scrutinizer

It somehow ascribed to me a problem in code which was unchanged by this PR. Correct it anyhow, along with some Phpstan fixes (errors now ignored because of change).

* Added Tests

Also corrected some docBlock problems with Style/*/parent and getSharedComponent.

* Create 2 Abstract Methods

Scrutinizer complained that 2 methods found in all Supervisor sub-types were not defined in Supervisor. Add abstract methods to satisfy it.

* Scrutinizer Ignoring Typehints

Try this instead.

* Slight Improvement

Better handling of Style->getParent().
2021-12-18 08:53:23 -08:00
leo-bsv a7f687fe5c
Xlsx image background in comments #1547 (#2422)
* XLSX Image background in comments

* XLSX-Image-Background-In-Comments (#1547)

* Test fixes, convertion for comment sizes from px to pt, fix for setting image sizes from zip, set image type

* Merge remote-tracking branch 'origin/XLSX-Image-Background-In-Comments' into XLSX-Image-Background-In-Comments

* Tests to check reloaded document.

Co-authored-by: Burkov Sergey
2021-12-17 06:10:59 -08:00
oleibman 5240a23117
Phpstan and Php8 Phase 2 (#2435)
PR #2428 reduced the count of Phpstan errors reported under Php8 from 218 to 13. This PR takes care of those 13, which could not necessarily be handled merely by tweaks to the configuration files.

The commonest problem was that Phpstan under Php7 thinks date_parse can return an array or false, but, under Php8, it thinks it can return only array. The documentation agrees with the Php7 interpretation, but I have not been able to construct a case, in any release of Php, where date_parse returns false. In case of error, it sets elements 'error' and 'error_count' in the returned array. Code is changed to handle either possibility in a manner of which Phpstan will approve.

Other problems are handled through type-hinting.
2021-12-09 23:11:19 -08:00
oleibman f0791aec7a
Phpstan and Php8 Phase 1 (#2428)
As configured, Phpstan running under Php7 reports no errors. However, running under Php8, it reports 218 (!) errors. The vast majority of these are due to two reasons:
- renaming parameters in Php builtin functions in preparation for named parameters.
- using the new class `GdImage` rather than type `resource` as the argument type for many image-based functions.

Regardless of the cause, this will be a problem sooner or later. This PR is an attempt to get ahead of that problem. It tweaks only the Phpstan configuration files, without changing any PhpSpreadsheet code. Php7 continues to report no errors, and the number of errors for Php8 is reduced to 13. Although those 13 can also be tweaked, there is a case to be made that code corrections might be better in at least some of those instances. I will attend to those as one or more PRs after this one.

Because this involves no changes to code, and because Phpstan baseline is a common cause of merge difficulties, I will probably merge this in a day or two, more quickly than I customarily do.
2021-12-03 07:37:51 -08:00
oleibman 580c741c8e
Improve PDF Support for Page Size and Orientation (#2410)
Fix #1691. PhpSpreadsheet allows the setting of different page size and orientation on each worksheet. It also allows the setting of page size and orientation on the PDF writer. It isn't clear which is supposed to prevail when the two are in conflict. In the cited issue, the user expects the PDF writer setting to prevail, and I tend to agree. Code is changed to do this, and handling things in this manner is now explicitly documented.

PhpSpreadsheet uses a default paper size of Letter, and a default orientation of Default (which Excel treats as Portrait). New static routines are added to change the default for sheets created subsequent to such calls. This could allow users to configure these defaults better for their environments. The new functions are added to the documentation.
2021-12-01 23:00:02 -08:00
oleibman 290c18e4db
Xlsx Reader Theme Support Broken After 17.1 (#2403)
Fix #2387. Fix #2075. There was substantial refactoring of Writer Xlsx styles in 18.0. An existing static property `$theme` was intended to be shared by both Writer Xlsx and the new Writer Xlsx Styles. However, the initialization of the property in the latter happened later than it should have. This PR makes that initialization happen as soon as the theme has been read. Also, declaring that property as static seems questionable; I have made it an instance member. This small re-factoring makes it possible to now support Themes in tab colors.

Since this PR changes Reader/Xlsx/Styles, add type-hinting throughout that module to eliminate Phpstan/Scrutinizer problems. I also removed method readStyle from Reader/Xlsx, since it was essentially duplicated in Reader/Xlsx/Styles. And I added a small number of tests to ensure that Styles is 100% covered. All of this is necessary in preparation for Namespacing phase 2.
2021-11-26 09:38:09 -08:00
oleibman 3257ae5c90
Rounding in NumberFormatter (#2399)
Fix #2385. NumberFormatter is using sprintf on a float, and is seeing inconsistent rounding as a result (it will also occasionally result in `-0`). Change to round the number before presenting it to sprintf.
2021-11-26 09:05:35 -08:00
oleibman b67404229a
Allow Skipping One Unit Test (#2402)
* Allow Skipping One Unit Test

Alone in the test suite, URLImageTest needs to access the internet. It's a little fragile (the site that it's looking for may go away or change), but no real problem. However, on my system, it runs afoul of my proxy. Rather than jumping through hoops when I run the test suite (which happens very often), I am changing the test to skip if an environment variable is set to a specific value. This should not adversely affect anyone, and the test will still run in github, but it will help me a lot.

* Scrutinizer

It complained that my one new if statement made the module too complex. There actually were a number of if-then-else situations that could be handled just as well with assertions. I have changed it accordingly.
2021-11-19 14:24:42 -08:00
Adrien Crivelli f46e3a1916
Use native typing for objects that were already documented as such 2021-11-18 11:08:29 +09:00
oleibman 2a12587f05
AutoFilter Improvements (#2393)
* AutoFilter Improvements

Fix issue #2378. The following changes are made:
- NotEqual tests must be part of a custom filter. Documentation has been changed to indicate that.
- Method setAndOr was replaced by setJoin some time ago. Documentation now reflects that change.
- Documentation to indicate that string filters are not case-sensitive, same as in Excel.
- Filters testing against numeric value now include a numeric test (not numeric for not equal, numeric for all others).
- String filter had previously treated everything as a test for "equal". It now handles "not equal" and the variants of "greater/less" with or without "equal".
- Documentation correctly stated that no more than 2 rules are allowed in a custom filter. Code did not enforce this restriction. It now does, throwing an exception if an attempt is made to add a third rule.
- Deleted a lot of comments in Rule.php to make it easier to see what is not yet implemented (between, begins with, etc.). I may take these on in future.
- Added a number of tests for the new functionality.

* Not Sure Why Phpstan Results Differ Local vs Github

Let's see if this change suffices.

* Phpstan Still

Not sure how to convince it. Let's try this.

* Phpstan Solved

Figured out the problem on my local machine. Expect this to work.
2021-11-16 07:46:07 -08:00
oleibman ffdae8efac
Update Some Doc Block Annotations (#2351)
* Update Some Doc Block Annotations

See PR #2010. That PR was never completed, and has gone stale. However, it was correct in identifying a situation where the doc block was not entirely accurate. It did not go far enough - several closely-related methods have similar problems. This PR attempts to fix the original problem and its close relations. Aside from the doc block changes, there are very minor changes to executable code. It also changes some of the unit tests targeted at the methods in question to eliminate mocking in favor of 'real' tests.

* Change Method to Static

Otherwise Scrutinizer will complain, even though Phpstan doesn't.

* Scrutinizer

Various clean-up activities.

* Scrutinizer

@#&$(*#&$ Got complexity down from 53 to (I think) 50. Don't really know what the target is.

* Code Changes Suggested By Review

Some improvements suggested in review by @PowerKiKi.

* Update Cells.php

* Merge Conflict

A change to a parameter name caused several problems when trying to fix it on Github. Fixing it locally should do the trick.

* Merge Conflicts in Phpstan Baseline

PR #2382 made a large number of changes to Phpstan Baseline, some of which conflicted with the Phpstan Baseline changes in this PR. This should resolve them all.
2021-11-11 23:38:05 -08:00
Adrien Crivelli 5a704158e1 Declare key of generic ArrayObject 2021-11-10 10:26:09 +09:00
Adrien Crivelli 49d47d4bb4 Update all deps 2021-11-08 10:20:47 +09:00
Adrien Crivelli 045db43d50 Rename even more parameters 2021-11-07 23:57:14 +09:00
oleibman 26c26ae8df
Xlsx Writer Support for WMF Files (#2339)
PR #1844 fixes it, but changes were requested. It has been almost 3 months and those changes have not been made. This PR replaces that one; it should be suitable for all supported releases of PHP through 8.1, and includes a formal unit test.

Fixes #1685
Closes #1844
2021-11-01 13:28:51 +09:00
Adrien Crivelli 59c706ebe7
Fix warnings in PHP 8.1 2021-10-31 23:12:33 +09:00
Adrien Crivelli c3c93c56d6
Fix CI 2021-10-31 22:17:07 +09:00
Adrien Crivelli 69f633420b
Merge branch 'master' into PHP8-Sane-Property-Names 2021-10-31 15:25:01 +09:00
Adrien Crivelli e550528c02
Lock our deps with our minimum PHP 7.2, instead of PHP 7.3 2021-10-30 12:54:26 +09:00
oleibman 3db0b2a2de
Corrections for HLOOKUP Function (#2330)
See issue #2123. HLOOKUP needs to do some conversions between column numbers and letters which it had not been doing.

HLOOKUP tests were performed using direct calls to the function in question rather than in the context of a spreadsheet. This contributed to keeping this error obscured even though there were, in theory, sufficient test cases. The tests are changed to perform in spreadsheet context. For the most part, the test cases are unchanged. One of the expected results was wrong; it has been changed, and a new case added to cover the case it was supposed to be testing.

After getting the HLOOKUP tests in order, it turned out that a test using literal arrays which had been succeeding now failed. The array constructed by the literals are considerably different than those constructed using spreadsheet cells; additional code was added to handle this situation.
2021-10-23 17:59:42 -07:00
oleibman 4dd5c06c7b
Deleting Sheet with Local Defined Name (#2284)
Fixes issue #2266. Writer/Xlsx fails when there is no longer a sheet which corresponds to the definition of a local defined name. The code is changed to drop such an orphaned name. Writer/Xls does not fail under the same cicrcumstances, so no correction is needed there. Writer/Ods fails in a different manner, and is corrected to no longer do so.
2021-09-15 12:14:13 -07:00
oleibman e02eab29f1
Validate Input to SetSelectedCells (#2280)
* Validate Input to SetSelectedCells

See issue #2279. User requests an enhancement so that you can set a Style on a Named Range. The attempt is failing because setting the style causes a call to setSelectedCells, which does not account for Named Ranges. Although not related to the issue, it is worth noting that setSelectedCells does nothing to attempt to validate its input.

The request seems reasonable, even if it is probably more than Excel itself offers. I have added code to setSelectedCells to recognize Named Ranges (if and only if they are defined on the sheet in question). It will throw an exception if the string passed as coordinates cannot be parsed as a range of cells or an appropriate Named Range, e.e.g. a Named Range on a different sheet, a non-existent named range, named formulas, formulas, use of sheet name qualifiers (even for the same sheet). Tests are, of course, added for all of those and for the original issue. The code in setSelectedCells is tested in a very large number of cases in the test suite, none of which showed any problems after this change.

* Scrutinizer

2 minor (non-fatal) corrections, including 1 where Phpstan and Scrutinizer have a different idea about return values from preg_replace.
2021-09-11 06:55:00 -07:00
oleibman de5f450856
Data Validations Referencing Another Sheet (#2265)
See issues #1432 and #2149. Data validations on an Xlsx worksheet can be specified in two manners - one (henceforth "internal") if a list is specified from the same sheet, and a different one (henceforth "external") if a list is specified from a different sheet. Xlsx worksheet reader formerly processed only the internal format; PR #2150 fixed this so that both would be processed correctly on read. However, Xlsx worksheet writer outputs data validators only in the internal format, and that does not work for external data validations; it appears, however, that internal data validations can be specified in external format.

This PR changes Xlsx worksheet writer to use only the external format. Somewhat surprisingly, this must come after most of the other XML tags that constitute a worksheet. It shares this characteristic (and XML tag) with conditional formatting. The new test case DataValidator2Test includes a worksheet which has both internal and external data validation, as well as conditional formatting.

There is some additional namespacing work supporting Data Validations that needs to happen on Xlsx reader. Since that is substantially unchanged with this PR, that work will happen in a future namespacing phase, probably phase 2. However, there are some non-namespace-related changes to Xlsx reader in this PR:
- Cell DataValidation adds support for a new property sqref, which is initialized through Xlsx reader using a setSqref method. If not initialized at write time, the code will work as it did before the introduction of this property. In particular, before this change, data validation applied to an entire column (as in the sample spreadsheet) would be applied only through the last populated row. In addition, this also allows a user to extend a Data Validation over a range of cells rather than just a single cell; the new method is added to the documentation.
- The topLeft property had formerly been used only for worksheets which use "freeze panes". However, as luck would have it, the sample dataset provided to demonstrate the Data Validations problem uses topLeft without freeze panes, slightly affecting the view when the spreadsheet is initially opened; PhpSpreadsheet will now do so as well.

It is worth noting issue #2262, which documents a problem with the hasValidValue method involving the calculation engine. That problem existed before this PR, and I do not yet have a handle on how it might be fixed.
2021-08-24 08:58:38 -07:00
oleibman 710f9f17a7
Fraction Formatting (#2254)
* Fraction Formatting

See issue #2253. User's analysis was correct - leading zeros in the decimal portion were being stripped out, so 0.0625 and 0.625 were being treated the same. As it turns out, integers also aren't handled well (`0 0/1` anyone?). The latter problem had been hidden because caller tested for integer first and skipped call if true; but FractionFormatter::format is public and should work correctly regardless. All Phpstan baseline entries for FractionFormatter and NumberFormatter are eliminated. New test data is added; no need for changes to test code.

* Scrutinizer

Ensure result is string.
2021-08-18 11:09:37 -07:00
oleibman 0cd20f3099
Csv Handling of Booleans (and an 8.1 Deprecation) (#2232)
* Csv Handling of Booleans (and an 8.1 Deprecation)

PhpSpreadsheet writes boolean values to a Csv as null-string/1, and treats input values of 'true' and 'false' as if they were strings. On the other hand, Excel writes boolean values to a Csv as TRUE/FALSE, and case-insensitively treats a matching string as boolean on read. This PR changes PhpSpreadsheet to match Excel.

A side-effect of this change is that it fixes behavior incorrectly reported as a bug in PR #2048. That issue was closed, correctly, as user error. The user had altered Csv Writer, including adding ```declare(strict_types=1);```; that declaration was the cause of the error. The "offending" statements, calls to strpbrk and str_replace, will now work correctly whether or not strict_types is in use.

And, just as I was getting ready to push this, the dailies for PHP 8.1 introduced a change deprecating auto_detect_line_endings. Csv Reader uses that setting; it allows it to process a Csv with Mac line endings, which happens to be something that Excel can do. As they say in https://wiki.php.net/rfc/deprecations_php_8_1, where the proposal passed without a single dissenting vote, "These newlines were used by “Classic” Mac OS, a system which has been discontinued in 2001, nearly two decades ago. Interoperability with such systems is no longer relevant." I tend to agree, but I don't know that we're ready to pull the plug yet. I don't see an easy way to emulate that functionality. For now, I have silenced the deprecation notices with at signs. I have also added a test case which will fail when support for that setting is pulled; this will give time to consider alternatives.

* Scrutinizer: Handling ini_set

This could be interesting. It doesn't like not handling an error condition for ini_set. Let's see if this satisfies it.
2021-08-04 07:00:17 -07:00
oleibman b9f6c70b86
New Looming Problems with PHP8.1 (#2231)
* New Looming Problems with PHP8.1

More deprecations. The following corrections are made in this PR:
- Calculation.php has a call to ctype_upper and apparently one of the samples manages to pass it an int. That function treats int differently from numeric strings, and that treatment is on the deprecation list. Enclosing the argument in quotes cannot cause a problem unless the int represents the ASCII value of an uppercase letter, which I cannot believe is the case; anyhow, if it is, the code will wind up with a nonsense result, e.g. if column is C and row is 1, the cell will be resolved as C1, but if column is int 67 (ASCII for C) and row is 1, the cell will be resolved as 671, not C1.
- Several Worksheet iterators need one or more functions to explicitly declare their return types. Thankfully, this does not seem to break earlier PHP versions.
- LocaleFloatsTest - see issue #1863. This was supposed to fail in PHP 8.0, but var_dump continued to support the old way (for 64-bit PHP only, not for 32-bit). PHP 8.1 appears to correct that omission, and the test will now fail. It doesn't show up as a failure in Github because of an accident - the attempt to set the locale to France in Github fails, so it skips the test before attempting the var_dump. But it does fail locally on my system. I have changed the test to use sprintf rather than var_dump; I think users are far more likely to use sprintf rather than var_dump in their applications. (They are, of course, even more likely to just cast to string, but the result of doing that is already different in 8.0 than in 7.4.) I would be equally happy to delete the test altogether.

There remain PHP 8.1 problems with Mpdf which are, of course, out of scope here.

There is one additional problem that I do not address in this ticket. The auto_detect_line_endings setting is being deprecated. This has some implications for Csv. I have another PR ready for Csv, and will discuss that problem there.

* Minor Scrutinizer Error

Hopefully fixed now.
2021-08-03 21:37:53 -07:00
oleibman 188d026615
Fix 112 Scrutinizer Problems in 1 Module (#2220)
* Fix 112 Scrutinizer Problems in 1 Module

The module is Reader/Xls/Escher - reading pictures from an Xls workbook. The errors fall into precisely 2 categories.
- Assigning a value to a variable which is not subsequently used (35). Although the statements therefore don't accomplish anything, I think they have documentary value for understanding the file layout. So, I have commented out the statements in question rather than deleting them.
- Class property `$this->object` can belong to any of several classes (77). When you invoke a method on it, Scrutinizer and Phpstan flag the statement if not all the candidate classes support the method. Neither has enough information to recognize that the method always exists for any object which reaches the statement. Scrutinizer is noisier about it - it issues a separate message for each class that doesn't support the method, while Phpstan issues a single message. Adding a `method_exists` test is sufficient for Phpstan. We'll see what Scrutinizer thinks when I push the change. If it still doesn't like it, we've eliminated only 35 problems. Phpunit coverage confirms that `method_exists` is always true at the appropriate point.

* Scrutinizer Can Be VERY Annoying

I wasn't looking to do a major rewrite. I was hoping 112 fixes would suffice. Oh well, let's see what happens now.
2021-07-26 20:13:26 -07:00
oleibman 51163713c7
Tweaks to Input File Validation (#2217)
* Tweaks to Input File Validation

This started as a response to issue #1718, for which it is a partial (not complete) solution. The following changes are made:
- canRead can currently throw an exception. This seems wrong. It should just return true/false.
- Breaking change of sorts. When AssertFile encounters a non-existent or unreadable file, it throws InvalidArgumentException. This does not make sense. I have changed it to throw PhpSpreadsheet/Reader/Exception.
- Since the previous bullet item required changing of most of the Reader files anyhow, this is a good time to add explicit typing for canRead in the function signature rather than the DocBlock. Since all the canRead functions inherit from an abstract version in IReader, they all have to be changed simulatneously. Except for Xlsx and Ods, most of the Reader files are otherwise unchanged.
- AssertFile is changed to add an optional "zip member" parameter. It will check for the existence of an appropriate member in what is supposed to be a zip file. It is used by Xlsx and Ods.
- Verifying that a given file is a valid zip ought to be a feature of ZipArchive. Thanks to a particularly nasty bug in php/libzip (see https://bugs.php.net/bug.php?id=81222), it is unsafe to attempt to open a zero-length file as a zip archive. There is a solution, but it does not apply to all the PHP releases which we support, and isn't even necessarily supported on all the point versions of the PHP versions which we do support. I have coded up a manual test for "valid zip", with a comment pointing to the spec.
- In theory, tests now cover 100% of the code in Shared/File. In practice ... One of the tests require that chmod works properly, which is not quite true on Windows systems, so that test is skipped on Windows. Another test requires that php.ini uses a non-default value for upload_temp_dir (can't be overridden in application code), which is probably not the case when Github runs the unit tests, so that test is skipped when appropriate. I have run tests for both on systems where they are not skipped.

* Update File.php

* Scrutinizer Timeout

It's not actually timing out, it's just waiting for something to finish that finished ages ago. Making a meaningless comment change in hopes that will clear the jam. Not particularly hopeful.
2021-07-24 20:44:04 -07:00
oleibman e8966183d3
Merge branch 'master' into chartcaption 2021-07-16 06:11:26 -07:00
oleibman 5507b96d7a
Merge branch 'master' into sheetpasswd 2021-07-13 06:11:47 -07:00
oleibman 8729a68338
Xls Reader Handle MACCENTRALEUROPE With or Without Hyphen (#2213)
* Xls Reader Handle MACCENTRALEUROPE With or Without Hyphen

Fixes issue #549 and https://github.com/Maatwebsite/Laravel-Excel/issues/989 (which is the source of the new test file). Some systems accept MACCENTRALEUROPE as the name for the appropriate encoding, and some accept MAC-CENTRALEUROPE. I fortunately have access to at least one of each type, and have run the tests on each.

CodePage.php has an array of translations from codepage number to string. I now allow the value to itself be an array; if so, the code will test each in turn to see if it can be used in iconv. I did not go fishing for other similar problems. If such show up, they can be dealt with in the same manner as this one. I don't really expect others, since this is a problem not merely for Xls, but, even then, it applies only to BIFF5 and earlier.

I also moved XlsTest from Reader to Reader/Xls.

* Cache Successful Result For Future Use

Per suggestion from @MarkBaker
2021-07-12 03:02:47 +02:00
oleibman 1ff2e50ed2
Merge branch 'master' into chartcaption 2021-07-02 14:35:29 -07:00
Owen Leibman ecb4a7fe27 DocBlock Changes for Chart/Title
This is a leftover Scrutinizer change, but it needed more attention than most others. Chart/Title DocBlocks define caption as `null|string`. However, in the wild, Excel usually presents the caption as an array, and not an array of strings but rather of RichText items. I am not sure why an array is needed since a RichText item can contain many text runs, but things are what they are.

Reader/Xlsx/ChartTitleTest reads a spreadsheet with the captions stored as a RichText array. Since it performs array operations on something the DocBlock says cannot be an array, Scrutinizer objects, although not seriously enough to fail the module. Phpstan also objects; its objection is silenced with an annotation. Aside from this test, there are other tests which do set the caption to a string, and Excel seems to handle that without a problem. So, I have changed the DocBlock to specify `array|RichText|String`. I have dropped null as a possibility; nullstring will do equally well.

Because getCaption can now return multiple datatypes, I think a new function which can return the text portion of the entire caption as a single string is needed. I have added it. This simplifies the test named above, and some code in Writer/Html. The latter is not part of unit testing because the version of JpGraph found in Composer is too antiquated. I verified the Html change manually by running samples/Chart/32_Chart_read_write_HTML.php using a recent version of JpGraph. It was as a result of this test that I uncovered issue #2203. I did not see anything about Charts in docs, so did not add a description of the new function there.

Phpstan is happy with the changes. We'll see how Scrutinizer feels when I push it.
2021-07-02 14:33:43 -07:00
oleibman 5523fc935b
Merge branch 'master' into sheetpasswd 2021-07-01 06:52:17 -07:00
Owen Leibman 560e9a885c CashFlow/Variable/NonPeriodic vs. Scrutinizer/Phpstan
Just reviewing Scrutinizer's list of "bugs". There are 19 ascribed to me. For some, I will definitely take no action (e.g. use of bitwise operators in AND, OR, and XOR functions). However, where I can clean things up so that Scrutinizer is satisfied and the resulting code is not too contorted, I will make an attempt.

This is the last of this set of changes. It corrects 2 problems according to Scrutinizer, and about 20 per Phpstan.
2021-07-01 12:11:41 +02:00
Owen Leibman b03544469b 2 Tests vs. Scrutinizer/Phpstan
Just reviewing Scrutinizer's list of "bugs". There are 19 ascribed to me. For some, I will definitely take no action (e.g. use of bitwise operators in AND, OR, and XOR functions). However, where I can clean things up so that Scrutinizer is satisfied and the resulting code is not too contorted, I will make an attempt.

This PR corrects 2 problems according to Scrutinizer, and 1 per Phpstan. Only test members are involved.
2021-07-01 11:15:02 +02:00
Owen Leibman 435ac30b47 Reader/Html vs. Scrutinizer/Phpstan
Just reviewing Scrutinizer's list of "bugs". There are 19 ascribed to me. For some, I will definitely take no action (e.g. use of bitwise operators in AND, OR, and XOR functions). However, where I can clean things up so that Scrutinizer is satisfied and the resulting code is not too contorted, I will make an attempt.

This PR corrects 2 problems according to Scrutinizer, and about 30 per Phpstan.
2021-07-01 10:15:06 +02:00
Owen Leibman 7b3585c76a Now That SettingsTest Is Well-Behaved
7 tests that needed to invoke Settings::setLibXmlLoaderOptions no longer need to do so.
2021-06-30 13:15:20 -07:00
oleibman 2ae948a319
Reader/Slk vs. Scrutinizer/Phpstan (#2192)
Just reviewing Scrutinizer's list of "bugs". There are 19 ascribed to me. For some, I will definitely take no action (e.g. use of bitwise operators in AND, OR, and XOR functions). However, where I can clean things up so that Scrutinizer is satisfied and the resulting code is not too contorted, I will make an attempt.

This PR corrects 3 problems (2 mine) according to Scrutinizer, and 7 per Phpstan. It also moves the Reader Slk tests under their own directory, as is the case for all the other Reader types.
2021-06-29 20:48:31 +02:00
Owen Leibman 36b328a9fa Fix Worksheet Passwords
Fix for issue #1897.

The existing hashing code seems to work correctly almost all the time, but there are exceptions. It is replaced by an exact implementation of the spec, including a link to the spec in the comments. Cases known to fail are added to the unit test suite.

The spec expects the string to be at most 255 bytes (yes, bytes not characters). The program had permitted any length; it will now throw an exception when the maximum length is exceeded.

Xls does not support any hashing algorithm except basic. The Xls writer had, nevertheless, accepted the results of any of the other possible algorithms. This leads to (a) a worksheet that can't be unprotected, and (b) deprecation notices during the write (because it is using hexdec, which expects only hex characters, and the other algorithms generate non-hex characters). I have changed Xls writer to ignore passwords generated by other algorithms. An alternative would be to have the password hasher generate both an algorithmic password (for use by Xlsx) and a basic password (for use by Xls); I think that is too complex a solution, but can look into it if you think it worthwhile.

I do not see any current support for Worksheet passwords in ODS Reader or Writer. I did not add support in this PR.

I added a new test to confirm the password for reading a spreadsheet is consistent with the one used for writing it. As you can see from the comments for the new test, it had an unusual problem with a somewhat unusual solution.
2021-06-29 09:11:51 -07:00
oleibman cd84020693
Xlsx Reader Better Namespace Handling Phase 1 Try2 (#2173)
* Xlsx Reader Better Namespace Handling Phase 1 Try2

This is a replacement for #2088, which has run into merge conflicts. I will close that PR in the near future, however the comments in that PR may prove useful for this one. While that PR has been in draft status all along, I am marking this one as ready. I will gladly add additional tests (and, of course, make code changes) that anyone has to suggest, but, with my most recent test files which I will describe in a separate comment, I have no further ideas on useful additions.

As mentioned in the earlier ticket, this is a risky change. But, as has been demonstrated, delaying it comes with its own set of risks. It would be helpful to have a temporary moratorium on changes to Reader/Xlsx until this change is merged.

The original commit message follows.

There have been a number of issues concerning the handling of legitimate but unexpected namespace prefixes in Xlsx spreadsheets created by software other than Excel and PhpSpreadsheet/PhpExcel.I have studied them, but, till now, have not had a good idea on how to act on them. A recent comment https://github.com/PHPOffice/PhpSpreadsheet/issues/860#issuecomment-824926224 in issue #860 by @IMSoP has triggered an idea about how to proceed.

Gnumeric Reader was recently changed to handle namespaces better. Using that as a model, this PR begins the process of doing the same for Xlsx. Xlsx is much larger and more complicated than Gnumeric, hence the need to tackle it in multiple phases. I believe that this PR handles all of:
- listWorkSheetNames
- listWorkSheetInfo. Note that there was a bug in this function which would cause it to count only used columns rather than all columns. That bug is corrected.
- active sheet
- selected cell and top left cell
- cell content (formulas, numbers, text)
- hyperlinks
- comments (partial - see below)

This PR does not address:
- styles
- images and charts
- VBA and ribbons
- many other items, I'm sure

The issue for non-standard namespacing till now has been the use of unexpected prefixes. While I was working on this change, @Lambik introduced issue #2067 PR #2068 which introduced a completely different problem - the use of unexpected URLs. That PR and the issue associated with it were quite well documented, including the supplying of a test file and tests for it. I asked if I could take a look to see if it could be integrated with my change, and the result seems to be yes, so those changes are also part of this PR.

While adding a comment to my test file, I discovered that Microsoft had added "threaded comments" as a new feature. I believe these are not yet supported by PhpSpreadsheet, and I am not going to add it, at least not now. I believe that, among other things, this will make identifying the author of a comment more difficult.

Although there are a number of Phpstan baseline changes as part of this PR, I did not attempt to resolve all Phpstan reports for Reader/Xlsx. Nor did I do anything to increase coverage. This change is already large and complex enough without those efforts.
2021-06-25 09:05:49 +02:00
Owen Leibman d0dd5b4594 Use WildcardMatch
Per suggestion from @MarkBaker.

WildcardMatch did not handle double tilde correctly. It has been changed to do so and its logic simplified (and commented).

Existing AutoFilter test covered this situation, but I added a test for MATCH as well.
2021-06-24 10:09:21 +02:00
Owen Leibman a735afc088 Autofilter Part 2
Most of the remaining 32-bit-unsafe date handling that remains in PhpSpreadsheet is in AutoFilter. Cleaning this up demonstrated that there are a lot of problems with AutoFilter, and I will do it in two pieces. Part 1 was PR #2141 which I have just merged.

In this PR:
- Fix remaining 32-bit dates in filterTestInDateGroupSet.
- Also in some of the existing AutoFilter samples. Note that the comments in two of those said the filter was being set for the first day of each month, but the code specifies the last day - I have corrected the comments.
- Remove mocking in unit tests for AutoFilter in favor of 'real' tests.
- Code coverage is now 100% in all of AutoFilter, AutoFilter/Column, and AutoFilter/Common/Rule.
- No remaining AutoFilter(/Column(/Rule)) exceptions in Phpstan baseline.
- Documentation for escaping of asterisk, question mark, and tilde in text filters included spurious backslashes which are now removed.
- Text filter escaping of question mark did not work. There had been no unit tests for any text filtering.
- Likewise there had been no testing for TopTen.
- Above- and below- average filters were not working because they acquired their Calculation instance incorrectly. There had been no tests.
- Several unchanging private static arrays in Rule were changed to private const arrays.
- Clones are now tested.
- RuleTest is moved to same directory as other tests.
2021-06-24 10:09:21 +02:00