diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index fb5aadc331..94fa0bbfe6 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -4342,7 +4342,7 @@ parameters: - message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#" - count: 4 + count: 3 path: src/Controllers/Sql/SqlController.php - @@ -16440,11 +16440,6 @@ parameters: count: 2 path: src/Util.php - - - message: "#^Cannot access offset mixed on mixed\\.$#" - count: 1 - path: src/Util.php - - message: "#^Cannot cast mixed to string\\.$#" count: 1 @@ -16535,6 +16530,11 @@ parameters: count: 1 path: src/Util.php + - + message: "#^Parameter \\#2 \\$array of function array_key_exists expects array, mixed given\\.$#" + count: 1 + path: src/Util.php + - message: "#^Parameter \\#2 \\$table of method PhpMyAdmin\\\\DatabaseInterface\\:\\:getTablesFull\\(\\) expects array\\|string, mixed given\\.$#" count: 1 diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 5e3ded5125..12d4c29381 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -4036,22 +4036,22 @@ $newCol - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + $newCol @@ -11522,7 +11522,7 @@ $type - + @@ -12301,13 +12301,15 @@ $byteUnits[$d] $units[$d] + + $array + $columnNames - $array[$p] @@ -12334,8 +12336,6 @@ - $array[$p] - $array[$p] @@ -12356,8 +12356,6 @@ $lastIndex - $p - $p $row $unit $value @@ -15773,6 +15771,7 @@ providerForTestBackquote providerForTestGetLowerCaseNames providerForTestGetMySQLDocuURL + providerForTestGetValueByKey providerFormatByteDown providerFormatNumber providerForwardedHeaders diff --git a/src/Controllers/Table/Structure/SaveController.php b/src/Controllers/Table/Structure/SaveController.php index 80b7bb8c17..c3ef125c39 100644 --- a/src/Controllers/Table/Structure/SaveController.php +++ b/src/Controllers/Table/Structure/SaveController.php @@ -80,20 +80,20 @@ final class SaveController extends AbstractController } $changes[] = 'CHANGE ' . Table::generateAlter( - Util::getValueByKey($_POST, 'field_orig.' . $i, ''), + Util::getValueByKey($_POST, ['field_orig', $i], ''), $_POST['field_name'][$i], $_POST['field_type'][$i], $_POST['field_length'][$i], $_POST['field_attribute'][$i], - Util::getValueByKey($_POST, 'field_collation.' . $i, ''), - Util::getValueByKey($_POST, 'field_null.' . $i, 'NO'), + Util::getValueByKey($_POST, ['field_collation', $i], ''), + Util::getValueByKey($_POST, ['field_null', $i], 'NO'), $_POST['field_default_type'][$i], $_POST['field_default_value'][$i], - Util::getValueByKey($_POST, 'field_extra.' . $i, ''), - Util::getValueByKey($_POST, 'field_comments.' . $i, ''), - Util::getValueByKey($_POST, 'field_virtuality.' . $i, ''), - Util::getValueByKey($_POST, 'field_expression.' . $i, ''), - Util::getValueByKey($_POST, 'field_move_to.' . $i, ''), + Util::getValueByKey($_POST, ['field_extra', $i], ''), + Util::getValueByKey($_POST, ['field_comments', $i], ''), + Util::getValueByKey($_POST, ['field_virtuality', $i], ''), + Util::getValueByKey($_POST, ['field_expression', $i], ''), + Util::getValueByKey($_POST, ['field_move_to', $i], ''), $columnsWithIndex, ); @@ -232,20 +232,20 @@ final class SaveController extends AbstractController } $changesRevert[] = 'CHANGE ' . Table::generateAlter( - Util::getValueByKey($_POST, 'field_orig.' . $i, ''), + Util::getValueByKey($_POST, ['field_orig', $i], ''), $_POST['field_name'][$i], $_POST['field_type_orig'][$i], $_POST['field_length_orig'][$i], $_POST['field_attribute_orig'][$i], - Util::getValueByKey($_POST, 'field_collation_orig.' . $i, ''), - Util::getValueByKey($_POST, 'field_null_orig.' . $i, 'NO'), + Util::getValueByKey($_POST, ['field_collation_orig', $i], ''), + Util::getValueByKey($_POST, ['field_null_orig', $i], 'NO'), $_POST['field_default_type_orig'][$i], $_POST['field_default_value_orig'][$i], - Util::getValueByKey($_POST, 'field_extra_orig.' . $i, ''), - Util::getValueByKey($_POST, 'field_comments_orig.' . $i, ''), - Util::getValueByKey($_POST, 'field_virtuality_orig.' . $i, ''), - Util::getValueByKey($_POST, 'field_expression_orig.' . $i, ''), - Util::getValueByKey($_POST, 'field_move_to_orig.' . $i, ''), + Util::getValueByKey($_POST, ['field_extra_orig', $i], ''), + Util::getValueByKey($_POST, ['field_comments_orig', $i], ''), + Util::getValueByKey($_POST, ['field_virtuality_orig', $i], ''), + Util::getValueByKey($_POST, ['field_expression_orig', $i], ''), + Util::getValueByKey($_POST, ['field_move_to_orig', $i], ''), ); } diff --git a/src/Query/Cache.php b/src/Query/Cache.php index 4f3173c681..6ec80a8b63 100644 --- a/src/Query/Cache.php +++ b/src/Query/Cache.php @@ -75,8 +75,8 @@ class Cache /** * Get a cached value from table cache. * - * @param mixed[] $contentPath Array of the name of the target value - * @param mixed $default Return value on cache miss + * @param (int|string)[] $contentPath Array of the name of the target value + * @param mixed $default Return value on cache miss * * @return mixed cached value or default */ diff --git a/src/Table/ColumnsDefinition.php b/src/Table/ColumnsDefinition.php index cc534e0ac1..10dcbda48c 100644 --- a/src/Table/ColumnsDefinition.php +++ b/src/Table/ColumnsDefinition.php @@ -160,21 +160,21 @@ final class ColumnsDefinition if ($regenerate) { $columnMeta = $this->getColumnMetaForRegeneratedFields($columnNumber); - $length = Util::getValueByKey($_POST, 'field_length.' . $columnNumber, $length); - $submitAttribute = Util::getValueByKey($_POST, 'field_attribute.' . $columnNumber, false); - $commentsMap[$columnMeta['Field']] = Util::getValueByKey($_POST, 'field_comments.' . $columnNumber); + $length = Util::getValueByKey($_POST, ['field_length', $columnNumber], $length); + $submitAttribute = Util::getValueByKey($_POST, ['field_attribute', $columnNumber], false); + $commentsMap[$columnMeta['Field']] = Util::getValueByKey($_POST, ['field_comments', $columnNumber]); $GLOBALS['mime_map'][$columnMeta['Field']] = array_merge( $GLOBALS['mime_map'][$columnMeta['Field']] ?? [], [ - 'mimetype' => Util::getValueByKey($_POST, 'field_mimetype.' . $columnNumber), + 'mimetype' => Util::getValueByKey($_POST, ['field_mimetype', $columnNumber]), 'transformation' => Util::getValueByKey( $_POST, - 'field_transformation.' . $columnNumber, + ['field_transformation' , $columnNumber], ), 'transformation_options' => Util::getValueByKey( $_POST, - 'field_transformation_options.' . $columnNumber, + ['field_transformation_options' , $columnNumber], ), ], ); @@ -406,22 +406,22 @@ final class ColumnsDefinition private function getColumnMetaForRegeneratedFields(int $columnNumber): array { $columnMeta = [ - 'Field' => Util::getValueByKey($_POST, 'field_name.' . $columnNumber), - 'Type' => Util::getValueByKey($_POST, 'field_type.' . $columnNumber), - 'Collation' => Util::getValueByKey($_POST, 'field_collation.' . $columnNumber, ''), - 'Null' => Util::getValueByKey($_POST, 'field_null.' . $columnNumber, ''), - 'DefaultType' => Util::getValueByKey($_POST, 'field_default_type.' . $columnNumber, 'NONE'), - 'DefaultValue' => Util::getValueByKey($_POST, 'field_default_value.' . $columnNumber, ''), - 'Extra' => Util::getValueByKey($_POST, 'field_extra.' . $columnNumber), - 'Virtuality' => Util::getValueByKey($_POST, 'field_virtuality.' . $columnNumber, ''), - 'Expression' => Util::getValueByKey($_POST, 'field_expression.' . $columnNumber, ''), + 'Field' => Util::getValueByKey($_POST, ['field_name', $columnNumber]), + 'Type' => Util::getValueByKey($_POST, ['field_type', $columnNumber]), + 'Collation' => Util::getValueByKey($_POST, ['field_collation', $columnNumber], ''), + 'Null' => Util::getValueByKey($_POST, ['field_null', $columnNumber], ''), + 'DefaultType' => Util::getValueByKey($_POST, ['field_default_type', $columnNumber], 'NONE'), + 'DefaultValue' => Util::getValueByKey($_POST, ['field_default_value', $columnNumber], ''), + 'Extra' => Util::getValueByKey($_POST, ['field_extra', $columnNumber]), + 'Virtuality' => Util::getValueByKey($_POST, ['field_virtuality', $columnNumber], ''), + 'Expression' => Util::getValueByKey($_POST, ['field_expression', $columnNumber], ''), 'Key' => '', 'Comment' => false, ]; $parts = explode( '_', - Util::getValueByKey($_POST, 'field_key.' . $columnNumber, ''), + Util::getValueByKey($_POST, ['field_key', $columnNumber], ''), 2, ); if (count($parts) === 2 && $parts[1] == $columnNumber) { diff --git a/src/Util.php b/src/Util.php index e5a8788d7b..e5fcbfbd5e 100644 --- a/src/Util.php +++ b/src/Util.php @@ -18,7 +18,6 @@ use function _pgettext; use function abs; use function array_key_exists; use function array_map; -use function array_shift; use function array_unique; use function bin2hex; use function chr; @@ -1962,28 +1961,22 @@ class Util } /** - * Access to a multidimensional array by dot notation + * Access to a multidimensional array recursively by the keys specified in $path * * @param mixed[] $array List of values - * @param string|mixed[] $path Path to searched value + * @param (int|string)[] $path Path to searched value * @param mixed $default Default value * * @return mixed Searched value */ - public static function getValueByKey(array $array, string|array $path, mixed $default = null): mixed + public static function getValueByKey(array $array, array $path, mixed $default = null): mixed { - if (is_string($path)) { - $path = explode('.', $path); - } - - $p = array_shift($path); - while ($p !== null) { - if (! isset($array[$p])) { + foreach ($path as $key) { + if (! array_key_exists($key, $array)) { return $default; } - $array = $array[$p]; - $p = array_shift($path); + $array = $array[$key]; } return $array; diff --git a/tests/classes/UtilTest.php b/tests/classes/UtilTest.php index 51933d1693..da970594a1 100644 --- a/tests/classes/UtilTest.php +++ b/tests/classes/UtilTest.php @@ -1628,4 +1628,46 @@ SQL; ]; $this->assertSame($expected, Util::getSupportedDatatypes()); } + + /** + * @param mixed[] $array + * @param (string|int)[] $path + */ + #[DataProvider('providerForTestGetValueByKey')] + public function testGetValueByKey(mixed $expected, array $array, array $path, mixed $default = null): void + { + $this->assertSame($expected, Util::getValueByKey($array, $path, $default)); + } + + /** @return iterable */ + public static function providerForTestGetValueByKey(): iterable + { + yield 'array_has_all_keys' => [ + 'foo', + ['key1' => ['key2' => 'foo']], + ['key1', 'key2'], + null, + ]; + + yield 'key_not_found' => [ + 'def', + ['key1' => ['key2' => 'foo']], + ['key1', 'key3'], + 'def', + ]; + + yield 'subarray_requested' => [ + ['key2' => 'foo'], + ['key1' => ['key2' => 'foo']], + ['key1'], + 'def', + ]; + + yield 'no_keys_specified' => [ + ['key1' => ['key2' => 'foo']], + ['key1' => ['key2' => 'foo']], + [], + 'def', + ]; + } }