diff --git a/libraries/classes/Gis/GisGeometry.php b/libraries/classes/Gis/GisGeometry.php index 3fa6eab17e..8e1c8692e8 100644 --- a/libraries/classes/Gis/GisGeometry.php +++ b/libraries/classes/Gis/GisGeometry.php @@ -10,9 +10,9 @@ namespace PhpMyAdmin\Gis; use PhpMyAdmin\Image\ImageWrapper; use TCPDF; +use function array_map; use function defined; use function explode; -use function floatval; use function mb_strripos; use function mb_substr; use function mt_getrandmax; @@ -205,9 +205,9 @@ abstract class GisGeometry * @param array|null $scale_data data related to scaling * @param bool $linear if true, as a 1D array, else as a 2D array * - * @return array scaled points + * @return float[]|float[][] scaled points */ - protected function extractPoints($point_set, $scale_data, $linear = false): array + private function extractPointsInternal(string $point_set, array|null $scale_data, bool $linear): array { $points_arr = []; @@ -219,34 +219,63 @@ abstract class GisGeometry // Extract coordinates of the point $coordinates = explode(' ', $point); - if (isset($coordinates[0], $coordinates[1]) && trim($coordinates[0]) != '' && trim($coordinates[1]) != '') { - if ($scale_data != null) { - $x = ($coordinates[0] - $scale_data['x']) * $scale_data['scale']; - $y = $scale_data['height'] - - ($coordinates[1] - $scale_data['y']) * $scale_data['scale']; + if (isset($coordinates[1]) && trim($coordinates[0]) != '' && trim($coordinates[1]) != '') { + if ($scale_data === null) { + $x = (float) $coordinates[0]; + $y = (float) $coordinates[1]; } else { - $x = floatval(trim($coordinates[0])); - $y = floatval(trim($coordinates[1])); + $x = (float) (((float) $coordinates[0] - $scale_data['x']) * $scale_data['scale']); + $y = (float) ($scale_data['height'] + - ((float) $coordinates[1] - $scale_data['y']) * $scale_data['scale']); } } else { - $x = 0; - $y = 0; + $x = 0.0; + $y = 0.0; } - if (! $linear) { - $points_arr[] = [ - $x, - $y, - ]; - } else { + if ($linear) { $points_arr[] = $x; $points_arr[] = $y; + } else { + $points_arr[] = [$x, $y]; } } return $points_arr; } + /** + * Extracts points, scales and returns them as an array. + * + * @param string $wktCoords string of comma separated points + * @param array|null $scale_data data related to scaling + * + * @return float[][] scaled points + */ + protected function extractPoints(string $wktCoords, array|null $scale_data): array + { + /** @var float[][] $points_arr */ + $points_arr = $this->extractPointsInternal($wktCoords, $scale_data, false); + + return $points_arr; + } + + /** + * Extracts points, scales and returns them as an linear array. + * + * @param string $wktCoords string of comma separated points + * @param array|null $scale_data data related to scaling + * + * @return float[] scaled points + */ + protected function extractPointsLinear(string $wktCoords, array|null $scale_data): array + { + /** @var float[] $points_arr */ + $points_arr = $this->extractPointsInternal($wktCoords, $scale_data, true); + + return $points_arr; + } + /** * Generates JavaScript for adding an array of polygons to OpenLayers. * diff --git a/libraries/classes/Gis/GisMultiPoint.php b/libraries/classes/Gis/GisMultiPoint.php index ded89b4771..03756d55dd 100644 --- a/libraries/classes/Gis/GisMultiPoint.php +++ b/libraries/classes/Gis/GisMultiPoint.php @@ -186,7 +186,7 @@ class GisMultiPoint extends GisGeometry $row = ''; foreach ($points_arr as $point) { - if (((float) $point[0]) === 0.0 || ((float) $point[1]) === 0.0) { + if ($point[0] === 0.0 || $point[1] === 0.0) { continue; } diff --git a/libraries/classes/Gis/GisMultiPolygon.php b/libraries/classes/Gis/GisMultiPolygon.php index 3ff95d7901..4b49fade21 100644 --- a/libraries/classes/Gis/GisMultiPolygon.php +++ b/libraries/classes/Gis/GisMultiPolygon.php @@ -101,7 +101,7 @@ class GisMultiPolygon extends GisGeometry $points_arr = []; foreach ($wkt_rings as $wkt_ring) { - $ring = $this->extractPoints($wkt_ring, $scale_data, true); + $ring = $this->extractPointsLinear($wkt_ring, $scale_data); $points_arr = array_merge($points_arr, $ring); } @@ -155,7 +155,7 @@ class GisMultiPolygon extends GisGeometry $points_arr = []; foreach ($wkt_rings as $wkt_ring) { - $ring = $this->extractPoints($wkt_ring, $scale_data, true); + $ring = $this->extractPointsLinear($wkt_ring, $scale_data); $points_arr = array_merge($points_arr, $ring); } diff --git a/libraries/classes/Gis/GisPoint.php b/libraries/classes/Gis/GisPoint.php index 40f0c1234f..5c4c1496a6 100644 --- a/libraries/classes/Gis/GisPoint.php +++ b/libraries/classes/Gis/GisPoint.php @@ -80,13 +80,13 @@ class GisPoint extends GisGeometry // Trim to remove leading 'POINT(' and trailing ')' $point = mb_substr($spatial, 6, -1); - $points_arr = $this->extractPoints($point, $scale_data); + $points_arr = $this->extractPointsLinear($point, $scale_data); // draw a small circle to mark the point - if ($points_arr[0][0] != '' && $points_arr[0][1] != '') { + if ($points_arr[0] != '' && $points_arr[0] != '') { $image->arc( - (int) round($points_arr[0][0]), - (int) round($points_arr[0][1]), + (int) round($points_arr[0]), + (int) round($points_arr[1]), 7, 7, 0, @@ -97,8 +97,8 @@ class GisPoint extends GisGeometry if ($label !== '') { $image->string( 1, - (int) round($points_arr[0][0]), - (int) round($points_arr[0][1]), + (int) round($points_arr[0]), + (int) round($points_arr[1]), $label, $black, ); @@ -133,14 +133,14 @@ class GisPoint extends GisGeometry // Trim to remove leading 'POINT(' and trailing ')' $point = mb_substr($spatial, 6, -1); - $points_arr = $this->extractPoints($point, $scale_data); + $points_arr = $this->extractPointsLinear($point, $scale_data); // draw a small circle to mark the point - if ($points_arr[0][0] != '' && $points_arr[0][1] != '') { - $pdf->Circle($points_arr[0][0], $points_arr[0][1], 2, 0, 360, 'D', $line); + if ($points_arr[0] != '' && $points_arr[1] != '') { + $pdf->Circle($points_arr[0], $points_arr[1], 2, 0, 360, 'D', $line); // print label if applicable if ($label !== '') { - $pdf->setXY($points_arr[0][0], $points_arr[0][1]); + $pdf->setXY($points_arr[0], $points_arr[1]); $pdf->setFontSize(5); $pdf->Cell(0, 0, $label); } @@ -172,12 +172,12 @@ class GisPoint extends GisGeometry // Trim to remove leading 'POINT(' and trailing ')' $point = mb_substr($spatial, 6, -1); - $points_arr = $this->extractPoints($point, $scale_data); + $points_arr = $this->extractPointsLinear($point, $scale_data); $row = ''; - if (((float) $points_arr[0][0]) !== 0.0 && ((float) $points_arr[0][1]) !== 0.0) { - $row .= ' $val) { $row .= ' ' . $option . '="' . $val . '"'; } diff --git a/libraries/classes/Gis/GisPolygon.php b/libraries/classes/Gis/GisPolygon.php index 7dc5bc4252..d7449aa116 100644 --- a/libraries/classes/Gis/GisPolygon.php +++ b/libraries/classes/Gis/GisPolygon.php @@ -92,7 +92,7 @@ class GisPolygon extends GisGeometry $points_arr = []; $wkt_rings = explode('),(', $polygon); foreach ($wkt_rings as $wkt_ring) { - $ring = $this->extractPoints($wkt_ring, $scale_data, true); + $ring = $this->extractPointsLinear($wkt_ring, $scale_data); $points_arr = array_merge($points_arr, $ring); } @@ -133,7 +133,7 @@ class GisPolygon extends GisGeometry $points_arr = []; foreach ($wkt_rings as $wkt_ring) { - $ring = $this->extractPoints($wkt_ring, $scale_data, true); + $ring = $this->extractPointsLinear($wkt_ring, $scale_data); $points_arr = array_merge($points_arr, $ring); } diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index dbad6fe8f7..1aa665e00f 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -4200,13 +4200,23 @@ parameters: count: 1 path: libraries/classes/Footer.php + - + message: "#^Casting to float something that's already float\\.$#" + count: 2 + path: libraries/classes/Gis/GisGeometry.php + - message: "#^Method PhpMyAdmin\\\\Gis\\\\GisGeometry\\:\\:extractPoints\\(\\) has parameter \\$scale_data with no value type specified in iterable type array\\.$#" count: 1 path: libraries/classes/Gis/GisGeometry.php - - message: "#^Method PhpMyAdmin\\\\Gis\\\\GisGeometry\\:\\:extractPoints\\(\\) return type has no value type specified in iterable type array\\.$#" + message: "#^Method PhpMyAdmin\\\\Gis\\\\GisGeometry\\:\\:extractPointsInternal\\(\\) has parameter \\$scale_data with no value type specified in iterable type array\\.$#" + count: 1 + path: libraries/classes/Gis/GisGeometry.php + + - + message: "#^Method PhpMyAdmin\\\\Gis\\\\GisGeometry\\:\\:extractPointsLinear\\(\\) has parameter \\$scale_data with no value type specified in iterable type array\\.$#" count: 1 path: libraries/classes/Gis/GisGeometry.php @@ -4346,7 +4356,7 @@ parameters: path: libraries/classes/Gis/GisLineString.php - - message: "#^Cannot access offset int\\<0, max\\> on non\\-empty\\-array\\<'no_of_points'\\|int\\<0, max\\>, array\\{x\\: mixed, y\\: mixed\\}\\|int\\<0, max\\>\\>\\|int\\<1, max\\>\\.$#" + message: "#^Cannot access offset int\\<0, max\\> on non\\-empty\\-array\\<'no_of_points'\\|int\\<0, max\\>, array\\{x\\: float, y\\: float\\}\\|int\\<0, max\\>\\>\\|int\\<1, max\\>\\.$#" count: 1 path: libraries/classes/Gis/GisMultiLineString.php @@ -4436,12 +4446,12 @@ parameters: path: libraries/classes/Gis/GisMultiPoint.php - - message: "#^Cannot access offset int on non\\-empty\\-array\\<'no_of_lines'\\|int, array\\{no_of_points\\: int\\<0, max\\>, 0\\?\\: array\\{x\\: mixed, y\\: mixed\\}\\}\\|int\\<1, max\\>\\>\\|int\\<1, max\\>\\.$#" + message: "#^Cannot access offset int on non\\-empty\\-array\\<'no_of_lines'\\|int, array\\{no_of_points\\: int\\<0, max\\>, 0\\?\\: array\\{x\\: float, y\\: float\\}\\}\\|int\\<1, max\\>\\>\\|int\\<1, max\\>\\.$#" count: 1 path: libraries/classes/Gis/GisMultiPolygon.php - - message: "#^Cannot access offset int\\<0, max\\> on non\\-empty\\-array\\<'no_of_points'\\|int\\<0, max\\>, array\\{x\\: mixed, y\\: mixed\\}\\|int\\<0, max\\>\\>\\|int\\<1, max\\>\\.$#" + message: "#^Cannot access offset int\\<0, max\\> on non\\-empty\\-array\\<'no_of_points'\\|int\\<0, max\\>, array\\{x\\: float, y\\: float\\}\\|int\\<0, max\\>\\>\\|int\\<1, max\\>\\.$#" count: 1 path: libraries/classes/Gis/GisMultiPolygon.php @@ -4480,6 +4490,11 @@ parameters: count: 1 path: libraries/classes/Gis/GisMultiPolygon.php + - + message: "#^Parameter \\#1 \\$points of method PhpMyAdmin\\\\Image\\\\ImageWrapper\\:\\:filledPolygon\\(\\) expects array\\, array\\ given\\.$#" + count: 1 + path: libraries/classes/Gis/GisMultiPolygon.php + - message: "#^Parameter \\#2 \\$color of method PhpMyAdmin\\\\Image\\\\ImageWrapper\\:\\:filledPolygon\\(\\) expects int, int\\|false given\\.$#" count: 1 @@ -4536,7 +4551,7 @@ parameters: path: libraries/classes/Gis/GisPoint.php - - message: "#^Cannot access offset int\\<0, max\\> on non\\-empty\\-array\\<'no_of_points'\\|int\\<0, max\\>, array\\{x\\: mixed, y\\: mixed\\}\\|int\\<0, max\\>\\>\\|int\\<1, max\\>\\.$#" + message: "#^Cannot access offset int\\<0, max\\> on non\\-empty\\-array\\<'no_of_points'\\|int\\<0, max\\>, array\\{x\\: float, y\\: float\\}\\|int\\<0, max\\>\\>\\|int\\<1, max\\>\\.$#" count: 1 path: libraries/classes/Gis/GisPolygon.php @@ -4600,6 +4615,11 @@ parameters: count: 1 path: libraries/classes/Gis/GisPolygon.php + - + message: "#^Parameter \\#1 \\$points of method PhpMyAdmin\\\\Image\\\\ImageWrapper\\:\\:filledPolygon\\(\\) expects array\\, array\\ given\\.$#" + count: 1 + path: libraries/classes/Gis/GisPolygon.php + - message: "#^Parameter \\#2 \\$color of method PhpMyAdmin\\\\Image\\\\ImageWrapper\\:\\:filledPolygon\\(\\) expects int, int\\|false given\\.$#" count: 1 @@ -10221,7 +10241,7 @@ parameters: path: test/classes/Gis/GisGeometryCollectionTest.php - - message: "#^Method PhpMyAdmin\\\\Tests\\\\Gis\\\\GisGeometryTest\\:\\:providerForTestExtractPoints\\(\\) return type has no value type specified in iterable type array\\.$#" + message: "#^Method PhpMyAdmin\\\\Tests\\\\Gis\\\\GisGeometryTest\\:\\:providerForTestExtractPointsInternal\\(\\) return type has no value type specified in iterable type array\\.$#" count: 1 path: test/classes/Gis/GisGeometryTest.php @@ -10241,12 +10261,12 @@ parameters: path: test/classes/Gis/GisGeometryTest.php - - message: "#^Method PhpMyAdmin\\\\Tests\\\\Gis\\\\GisGeometryTest\\:\\:testExtractPoints\\(\\) has parameter \\$output with no value type specified in iterable type array\\.$#" + message: "#^Method PhpMyAdmin\\\\Tests\\\\Gis\\\\GisGeometryTest\\:\\:testExtractPointsInternal\\(\\) has parameter \\$output with no value type specified in iterable type array\\.$#" count: 1 path: test/classes/Gis/GisGeometryTest.php - - message: "#^Method PhpMyAdmin\\\\Tests\\\\Gis\\\\GisGeometryTest\\:\\:testExtractPoints\\(\\) has parameter \\$scale_data with no value type specified in iterable type array\\.$#" + message: "#^Method PhpMyAdmin\\\\Tests\\\\Gis\\\\GisGeometryTest\\:\\:testExtractPointsInternal\\(\\) has parameter \\$scale_data with no value type specified in iterable type array\\.$#" count: 1 path: test/classes/Gis/GisGeometryTest.php diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 9ed8ef58e1..5f1f1ea2b3 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -7235,20 +7235,16 @@ $line $point - $points_arr[] - $points_arr[] $polygon - $x - $y - - $point[0] $point[1] + + $last_comma @@ -7269,14 +7265,6 @@ - $point[0] - $point[0] - $point[1] - $point[1] - $points_arr[1][0] - $points_arr[1][0] - $points_arr[1][1] - $points_arr[1][1] $temp_point[0] $temp_point[0] $temp_point[1] @@ -7284,18 +7272,6 @@ - $point[0] - $point[0] - $point[0] - $point[1] - $point[1] - $point[1] - $points_arr[$i][0] - $points_arr[$i][1] - $points_arr[1][0] - $points_arr[1][0] - $points_arr[1][1] - $points_arr[1][1] $temp_point[0] $temp_point[0] $temp_point[1] @@ -7303,15 +7279,8 @@ $no_of_points - $point - $point - $point - $temp_point - $temp_point - $point[0] - $point[1] @@ -7329,14 +7298,6 @@ - $point[0] - $point[0] - $point[1] - $point[1] - $points_arr[1][0] - $points_arr[1][0] - $points_arr[1][1] - $points_arr[1][1] $temp_point[0] $temp_point[0] $temp_point[1] @@ -7349,18 +7310,6 @@ - $point[0] - $point[0] - $point[0] - $point[1] - $point[1] - $point[1] - $points[$i][0] - $points[$i][1] - $points_arr[1][0] - $points_arr[1][0] - $points_arr[1][1] - $points_arr[1][1] $temp_point[0] @@ -7373,17 +7322,10 @@ $no_of_lines $no_of_points $point - $point - $point - $point - $temp_point - $temp_point - $point[0] - $point[1] @@ -7405,37 +7347,11 @@ $point - $point[0] - $point[0] - $point[1] - $point[1] - $points_arr[0][0] - $points_arr[0][0] - $points_arr[0][1] - $points_arr[0][1] $point[0] - $point[0] - $point[0] - $point[0] - $point[0] - $point[0] - $point[0] $point[1] - $point[1] - $point[1] - $point[1] - $point[1] - $point[1] - $point[1] - $points[$i][0] - $points[$i][1] - $points_arr[0][0] - $points_arr[0][0] - $points_arr[0][1] - $points_arr[0][1] @@ -7444,13 +7360,8 @@ $no_of_points $point - $point - $point - $point - $point[0] - $point[1] $label_point[1] - $point[0] - $point[1] - $points[$i][0] - $points[$i][1] - $points_arr[0][0] - $points_arr[0][1] @@ -7549,7 +7454,6 @@ $no_of_points $no_of_polygons $point - $point $ring $ring $ring @@ -7562,10 +7466,6 @@ - $point[0] - $point[1] - $points_arr[0][0] - $points_arr[0][1] @@ -7585,38 +7485,13 @@ - - $points_arr[0] - $points_arr[0][0] - $points_arr[0][0] - $points_arr[0][0] - $points_arr[0][0] - $points_arr[0][1] - $points_arr[0][1] - $points_arr[0][1] - $points_arr[0][1] - - $points[0][0] - $points[0][1] - $points_arr[0][0] - $points_arr[0][0] - $points_arr[0][0] - $points_arr[0][0] - $points_arr[0][0] - $points_arr[0][1] - $points_arr[0][1] - $points_arr[0][1] - $points_arr[0][1] - $points_arr[0][1] - $points_arr[0][0] - $points_arr[0][1] $points_arr - $points_arr[2] - $points_arr[2] - $points_arr[3] - $points_arr[3] ($y1 - $y0) ** 2 + ($x0 - $x1) ** 2 @@ -7669,12 +7540,6 @@ - $point[0] - $point[1] - $points[$i][0] - $points[$i][1] - $points_arr[0][0] - $points_arr[0][1] @@ -7706,7 +7571,6 @@ $p1 $p1 $p2 - $point @@ -7732,10 +7596,6 @@ - $point[0] - $point[1] - $points_arr[0][0] - $points_arr[0][1] @@ -15883,6 +15743,9 @@ + + $points + array array diff --git a/test/classes/Gis/GisGeometryTest.php b/test/classes/Gis/GisGeometryTest.php index 75babf0249..6d0d850245 100644 --- a/test/classes/Gis/GisGeometryTest.php +++ b/test/classes/Gis/GisGeometryTest.php @@ -137,38 +137,40 @@ class GisGeometryTest extends AbstractTestCase } /** - * tests extractPoints method + * tests extractPointsInternal method * * @param string $point_set String of comma separated points * @param array|null $scale_data Data related to scaling * @param bool $linear If true, as a 1D array, else as a 2D array * @param array $output Expected output * - * @dataProvider providerForTestExtractPoints + * @dataProvider providerForTestExtractPointsInternal */ - public function testExtractPoints(string $point_set, array|null $scale_data, bool $linear, array $output): void - { - $this->assertEquals( - $output, - $this->callFunction( - $this->object, - GisGeometry::class, - 'extractPoints', - [ - $point_set, - $scale_data, - $linear, - ], - ), + public function testExtractPointsInternal( + string $point_set, + array|null $scale_data, + bool $linear, + array $output, + ): void { + $points = $this->callFunction( + $this->object, + GisGeometry::class, + 'extractPointsInternal', + [ + $point_set, + $scale_data, + $linear, + ], ); + $this->assertEquals($output, $points); } /** - * data provider for testExtractPoints + * data provider for testExtractPointsInternal * - * @return array data for testExtractPoints + * @return array data for testExtractPointsInternal */ - public static function providerForTestExtractPoints(): array + public static function providerForTestExtractPointsInternal(): array { return [ // with no scale data