Issue 2066, highlighting more validation needed for LookupRef Functions (#2069)
* Issue 2066, highlighting more validation needed for LookupRef Functions * Additional test cases
This commit is contained in:
parent
5ee4fbf090
commit
115e39ae0c
|
|
@ -975,11 +975,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/LookupRef/LookupBase.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#3 \\$rowNum of static method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\LookupRef\\\\Matrix\\:\\:extractRowValue\\(\\) expects int, float\\|int\\<0, max\\>\\|string given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\LookupRef\\\\Matrix\\:\\:extractRowValue\\(\\) has no return typehint specified\\.$#"
|
||||
count: 1
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\LookupRef;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
|
||||
class LookupRefValidations
|
||||
{
|
||||
/**
|
||||
* @param mixed $value
|
||||
*/
|
||||
public static function validateInt($value): int
|
||||
{
|
||||
if (!is_numeric($value)) {
|
||||
if (Functions::isError($value)) {
|
||||
throw new Exception($value);
|
||||
}
|
||||
|
||||
throw new Exception(Functions::VALUE());
|
||||
}
|
||||
|
||||
return (int) floor((float) $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
*/
|
||||
public static function validatePositiveInt($value, bool $allowZero = true): int
|
||||
{
|
||||
$value = self::validateInt($value);
|
||||
|
||||
if (($allowZero === false && $value <= 0) || $value < 0) {
|
||||
throw new Exception(Functions::VALUE());
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\LookupRef;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
|
||||
class Matrix
|
||||
|
|
@ -39,7 +40,7 @@ class Matrix
|
|||
* Uses an index to choose a value from a reference or array
|
||||
*
|
||||
* Excel Function:
|
||||
* =INDEX(range_array, row_num, [column_num])
|
||||
* =INDEX(range_array, row_num, [column_num], [area_num])
|
||||
*
|
||||
* @param mixed $matrix A range of cells or an array constant
|
||||
* @param mixed $rowNum The row in the array or range from which to return a value.
|
||||
|
|
@ -47,15 +48,20 @@ class Matrix
|
|||
* @param mixed $columnNum The column in the array or range from which to return a value.
|
||||
* If column_num is omitted, row_num is required.
|
||||
*
|
||||
* TODO Provide support for area_num, currently not supported
|
||||
*
|
||||
* @return mixed the value of a specified cell or array of cells
|
||||
*/
|
||||
public static function index($matrix, $rowNum = 0, $columnNum = 0)
|
||||
{
|
||||
$rowNum = Functions::flattenSingleValue($rowNum);
|
||||
$columnNum = Functions::flattenSingleValue($columnNum);
|
||||
$rowNum = ($rowNum === null) ? 0 : Functions::flattenSingleValue($rowNum);
|
||||
$columnNum = ($columnNum === null) ? 0 : Functions::flattenSingleValue($columnNum);
|
||||
|
||||
if (!is_numeric($rowNum) || !is_numeric($columnNum) || ($rowNum < 0) || ($columnNum < 0)) {
|
||||
return Functions::VALUE();
|
||||
try {
|
||||
$rowNum = LookupRefValidations::validatePositiveInt($rowNum);
|
||||
$columnNum = LookupRefValidations::validatePositiveInt($columnNum);
|
||||
} catch (Exception $e) {
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
if (!is_array($matrix) || ($rowNum > count($matrix))) {
|
||||
|
|
@ -69,12 +75,12 @@ class Matrix
|
|||
return Functions::REF();
|
||||
}
|
||||
|
||||
if ($columnNum == 0) {
|
||||
if ($columnNum === 0) {
|
||||
return self::extractRowValue($matrix, $rowKeys, $rowNum);
|
||||
}
|
||||
|
||||
$columnNum = $columnKeys[--$columnNum];
|
||||
if ($rowNum == 0) {
|
||||
if ($rowNum === 0) {
|
||||
return array_map(
|
||||
function ($value) {
|
||||
return [$value];
|
||||
|
|
@ -89,7 +95,7 @@ class Matrix
|
|||
|
||||
private static function extractRowValue(array $matrix, array $rowKeys, int $rowNum)
|
||||
{
|
||||
if ($rowNum == 0) {
|
||||
if ($rowNum === 0) {
|
||||
return $matrix;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ return [
|
|||
// Input
|
||||
[20 => ['R' => 1]],
|
||||
],
|
||||
[
|
||||
'Negative Row' => [
|
||||
'#VALUE!', // Expected
|
||||
// Input
|
||||
[
|
||||
|
|
@ -15,7 +15,7 @@ return [
|
|||
],
|
||||
-1,
|
||||
],
|
||||
[
|
||||
'Row > matrix rows' => [
|
||||
'#REF!', // Expected
|
||||
// Input
|
||||
[
|
||||
|
|
@ -24,7 +24,25 @@ return [
|
|||
],
|
||||
10,
|
||||
],
|
||||
[
|
||||
'Row is not a number' => [
|
||||
'#VALUE!', // Expected
|
||||
// Input
|
||||
[
|
||||
20 => ['R' => 1],
|
||||
21 => ['R' => 2],
|
||||
],
|
||||
'NaN',
|
||||
],
|
||||
'Row is Error' => [
|
||||
'#N/A', // Expected
|
||||
// Input
|
||||
[
|
||||
20 => ['R' => 1],
|
||||
21 => ['R' => 2],
|
||||
],
|
||||
'#N/A',
|
||||
],
|
||||
'Return row 2' => [
|
||||
[21 => ['R' => 2]], // Expected
|
||||
// Input
|
||||
[
|
||||
|
|
@ -33,7 +51,7 @@ return [
|
|||
],
|
||||
2,
|
||||
],
|
||||
[
|
||||
'Return row 2 from larger matrix' => [
|
||||
[21 => ['R' => 2, 'S' => 4]], // Expected
|
||||
// Input
|
||||
[
|
||||
|
|
@ -43,17 +61,17 @@ return [
|
|||
2,
|
||||
0,
|
||||
],
|
||||
[
|
||||
'Negative Column' => [
|
||||
'#VALUE!', // Expected
|
||||
// Input
|
||||
[
|
||||
'20' => ['R' => 1, 'S' => 3],
|
||||
'21' => ['R' => 2, 'S' => 4],
|
||||
],
|
||||
2,
|
||||
0,
|
||||
-1,
|
||||
],
|
||||
[
|
||||
'Column > matrix columns' => [
|
||||
'#REF!', // Expected
|
||||
// Input
|
||||
[
|
||||
|
|
@ -63,15 +81,25 @@ return [
|
|||
2,
|
||||
10,
|
||||
],
|
||||
[
|
||||
'#REF!', // Expected
|
||||
'Column is not a number' => [
|
||||
'#VALUE!', // Expected
|
||||
// Input
|
||||
[
|
||||
'20' => ['R' => 1, 'S' => 3],
|
||||
'21' => ['R' => 2, 'S' => 4],
|
||||
20 => ['R' => 1],
|
||||
21 => ['R' => 2],
|
||||
],
|
||||
10,
|
||||
2,
|
||||
1,
|
||||
'NaN',
|
||||
],
|
||||
'Column is Error' => [
|
||||
'#N/A', // Expected
|
||||
// Input
|
||||
[
|
||||
20 => ['R' => 1],
|
||||
21 => ['R' => 2],
|
||||
],
|
||||
1,
|
||||
'#N/A',
|
||||
],
|
||||
[
|
||||
4, // Expected
|
||||
|
|
@ -115,6 +143,15 @@ return [
|
|||
2,
|
||||
1,
|
||||
],
|
||||
[
|
||||
[1 => ['Bananas', 'Pears']],
|
||||
[
|
||||
['Apples', 'Lemons'],
|
||||
['Bananas', 'Pears'],
|
||||
],
|
||||
2,
|
||||
0,
|
||||
],
|
||||
[
|
||||
3,
|
||||
[
|
||||
|
|
|
|||
Loading…
Reference in New Issue