From ca90379dc421c6a05059890961cbc0cde5af40ac Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Sat, 27 Aug 2022 23:15:16 -0700 Subject: [PATCH] 2 Minor Phpstan-related Fixes (#3030) For one of the Phpstan upgrades, some message text had changed so drastically that the only practical solution at the time was to move the messages from phpstan-baseline.neon to phpstan.neon.dist. This was not ideal, but it allowed us time to move on and study the errors, which I have now done. At one point, Parser is expecting a variable to be an array, and that was not clear from the code. If not an array, the code will error out (which was Phpstan's concern); I have changed it to throw an exception instead. This satisfies Phpstan, and I can get the message out of neon.dist (without needing to restore it to baseline). Unsurprisingly, the exception was never thrown in the existing test suite, although I added a couple of tests to exercise that code. In Helper/Dimension, Phpstan flagged a statement inappropriately. I suppressed the message using an annotation and filed a bug report https://github.com/phpstan/phpstan/issues/7563. A fix for the problem was merged yesterday, which is good, but it puts us in a tenuous position. The annotation is needed now, but, when the fix is inevitably pushed to the version we use, the no-longer-needed annotation will trigger a different message. Recode so that neither the current nor the future versions will issue a message, eliminating the annotation in the process. --- phpstan.neon.dist | 5 -- src/PhpSpreadsheet/Helper/Dimension.php | 14 ++++- src/PhpSpreadsheet/Writer/Xls/Parser.php | 7 ++- .../Writer/Xls/ParserTest.php | 56 +++++++++++++++++++ 4 files changed, 73 insertions(+), 9 deletions(-) create mode 100644 tests/PhpSpreadsheetTests/Writer/Xls/ParserTest.php diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 5cac36a1..64b325c6 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -21,8 +21,3 @@ parameters: # Accept a bit anything for assert methods - '~^Parameter \#2 .* of static method PHPUnit\\Framework\\Assert\:\:assert\w+\(\) expects .*, .* given\.$~' - '~^Method PhpOffice\\PhpSpreadsheetTests\\.*\:\:test.*\(\) has parameter \$args with no type specified\.$~' - - # Some issues in Xls/Parser between 1.6.3 and 1.7.7 - - - message: "#^Offset '(left|right|value)' does not exist on (non-empty-array\\|string|array\\|null)\\.$#" - path: src/PhpSpreadsheet/Writer/Xls/Parser.php diff --git a/src/PhpSpreadsheet/Helper/Dimension.php b/src/PhpSpreadsheet/Helper/Dimension.php index 425c9a61..ff07ce5b 100644 --- a/src/PhpSpreadsheet/Helper/Dimension.php +++ b/src/PhpSpreadsheet/Helper/Dimension.php @@ -55,10 +55,20 @@ class Dimension */ protected $unit; + /** + * Phpstan bug has been fixed; this function allows us to + * pass Phpstan whether fixed or not. + * + * @param mixed $value + */ + private static function stanBugFixed($value): array + { + return is_array($value) ? $value : [null, null]; + } + public function __construct(string $dimension) { - // @phpstan-ignore-next-line - [$size, $unit] = sscanf($dimension, '%[1234567890.]%s'); + [$size, $unit] = self::stanBugFixed(sscanf($dimension, '%[1234567890.]%s')); $unit = strtolower(trim($unit ?? '')); $size = (float) $size; diff --git a/src/PhpSpreadsheet/Writer/Xls/Parser.php b/src/PhpSpreadsheet/Writer/Xls/Parser.php index ca9b67b5..ca407d2a 100644 --- a/src/PhpSpreadsheet/Writer/Xls/Parser.php +++ b/src/PhpSpreadsheet/Writer/Xls/Parser.php @@ -78,7 +78,7 @@ class Parser /** * The parse tree to be generated. * - * @var string + * @var array|string */ public $parseTree; @@ -1445,6 +1445,9 @@ class Parser if (empty($tree)) { // If it's the first call use parseTree $tree = $this->parseTree; } + if (!is_array($tree) || !isset($tree['left'], $tree['right'], $tree['value'])) { + throw new WriterException('Unexpected non-array'); + } if (is_array($tree['left'])) { $converted_tree = $this->toReversePolish($tree['left']); @@ -1475,7 +1478,7 @@ class Parser $left_tree = ''; } - // add it's left subtree and return. + // add its left subtree and return. return $left_tree . $this->convertFunction($tree['value'], $tree['right']); } $converted_tree = $this->convert($tree['value']); diff --git a/tests/PhpSpreadsheetTests/Writer/Xls/ParserTest.php b/tests/PhpSpreadsheetTests/Writer/Xls/ParserTest.php new file mode 100644 index 00000000..38fd29d3 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Writer/Xls/ParserTest.php @@ -0,0 +1,56 @@ +spreadsheet !== null) { + $this->spreadsheet->disconnectWorksheets(); + $this->spreadsheet = null; + } + } + + public function testNonArray(): void + { + $this->expectException(WriterException::class); + $this->expectExceptionMessage('Unexpected non-array'); + $this->spreadsheet = new Spreadsheet(); + $parser = new Parser($this->spreadsheet); + $parser->toReversePolish(); + } + + public function testMissingIndex(): void + { + $this->expectException(WriterException::class); + $this->expectExceptionMessage('Unexpected non-array'); + $this->spreadsheet = new Spreadsheet(); + $parser = new Parser($this->spreadsheet); + $parser->toReversePolish(['left' => 0]); + } + + public function testParseError(): void + { + $this->expectException(WriterException::class); + $this->expectExceptionMessage('Unknown token +'); + $this->spreadsheet = new Spreadsheet(); + $parser = new Parser($this->spreadsheet); + $parser->toReversePolish(['left' => 1, 'right' => 2, 'value' => '+']); + } + + public function testGoodParse(): void + { + $this->spreadsheet = new Spreadsheet(); + $parser = new Parser($this->spreadsheet); + self::assertSame('1e01001e02001e0300', bin2hex($parser->toReversePolish(['left' => 1, 'right' => 2, 'value' => 3]))); + } +}