Skip to content

Commit

Permalink
Fix WKT geometry string provided by QGIS Server in GetFeatureInfo
Browse files Browse the repository at this point in the history
The WKT geometry provided by QGIS Server in GetFeatureInfo does not contain a space between the geometry type and the dimension.

Funded by Syslor https://syslor.net
  • Loading branch information
rldhont committed Feb 7, 2025
1 parent e3f7f12 commit 9ef5e7a
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 20 deletions.
68 changes: 50 additions & 18 deletions lizmap/modules/lizmap/classes/lizmapWkt.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
*
* @license Mozilla Public License : http://www.mozilla.org/MPL/
*/

/**
* @phpstan-type WktMatches array{geomType: string, dim: string, str: string}
*/
class lizmapWkt
{
/** @var array<string, string> */
Expand All @@ -24,7 +28,7 @@ class lizmapWkt
*
* @param string $wkt A WKT string
*
* @return array|false The WKT string is well formed
* @return false|WktMatches The WKT string is well formed
*/
public static function check($wkt)
{
Expand All @@ -42,13 +46,55 @@ public static function check($wkt)
return false;
}

$geomType = strtolower($matches[1]);
$dim = strtolower($matches[2]);
$str = $matches[3];

if (substr($geomType, -2) === 'zm') {
$geomType = substr($geomType, 0, -2);
$dim = 'zm';
} elseif (substr($geomType, -2) === 'mz') {
$geomType = substr($geomType, 0, -2);
$dim = 'mz';
} elseif (substr($geomType, -1) === 'z') {
$geomType = substr($geomType, 0, -1);
$dim = 'z';
} elseif (substr($geomType, -1) === 'm') {
$geomType = substr($geomType, 0, -1);
$dim = 'm';
}

return array(
'geomType' => strtolower($matches[1]),
'dim' => strtolower($matches[2]),
'str' => $matches[3],
'geomType' => $geomType,
'dim' => $dim,
'str' => $str,
);
}

/**
* Return a WKT string corrected with space between geometry type and dimension as upper case.
*
* @param string $wkt A WKT string
*
* @return null|string The WKT string corrected with space between geometry type and dimension as upper case
*/
public static function fix($wkt)
{
// Checking and extracting geometry type, dimension and coordinates
$matches = self::check($wkt);
if (!$matches) {
return null;
}

$nWkt = $matches['geomType'];
if ($matches['dim'] !== '') {
$nWkt .= ' '.$matches['dim'];
}
$nWkt .= ' ('.$matches['str'].')';

return strtoupper($nWkt);
}

/**
* Return a geometry array likes it is defined in GeoJSON.
*
Expand All @@ -67,20 +113,6 @@ public static function parse($wkt)
$dim = $matches['dim'];
$str = $matches['str'];

if (substr($geomType, -2) === 'zm') {
$geomType = substr($geomType, 0, -2);
$dim = 'zm';
} elseif (substr($geomType, -2) === 'mz') {
$geomType = substr($geomType, 0, -2);
$dim = 'mz';
} elseif (substr($geomType, -1) === 'z') {
$geomType = substr($geomType, 0, -1);
$dim = 'z';
} elseif (substr($geomType, -1) === 'm') {
$geomType = substr($geomType, 0, -1);
$dim = 'm';
}

// Get coordinates
$coordinates = null;
if ($geomType === 'point') {
Expand Down
6 changes: 5 additions & 1 deletion lizmap/modules/lizmap/lib/Request/WMSRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,11 @@ protected function gfiVectorXmlToHtml($layerId, $layerName, $layerTitle, $layer,
'maxy' => 'bbox-maxy',
);
if ($feature->BoundingBox) {
$hiddenGeometry .= '<input type="hidden" value="'.$attribute['value'].'" class="lizmap-popup-layer-feature-geometry"/>'.PHP_EOL;
// Fix geometry by adding space between geometry type and Z, M or ZM
$geom = \lizmapWkt::fix($attribute['value']);
// Insert geometry as an hidden input
$hiddenGeometry .= '<input type="hidden" value="'.$geom.'" class="lizmap-popup-layer-feature-geometry"/>'.PHP_EOL;
// Insert bounding box data as hidden inputs
$bbox = $feature->BoundingBox[0];
foreach ($props as $prop => $class) {
$hiddenGeometry .= '<input type="hidden" value="'.$bbox[$prop].'" class="lizmap-popup-layer-feature-'.$class.'"/>'.PHP_EOL;
Expand Down
56 changes: 55 additions & 1 deletion tests/units/classes/lizmapWktTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,32 @@ function testChecking() {
'GEOMETRY (((30 10, 40 40, 20 40, 10 20, 30 10)))',
);
foreach($wktArray as $wkt) {
$this->assertIsArray(lizmapWkt::check($wkt), 'The '.$wkt.' has not been checked!');
$checked = lizmapWkt::check($wkt);
$this->assertIsArray($checked, 'The '.$wkt.' has not been checked!');
$this->assertArrayHasKey('geomType', $checked);
$this->assertArrayHasKey('dim', $checked);
$this->assertEquals('', $checked['dim']);
$this->assertArrayHasKey('str', $checked);
}

$zWktArray = array(
'POINT Z (30 10 0)',
'POINT Z(30 10 0)',
'POINTZ(30 10 0)',
'LINESTRING Z (30 10 0, 10 30 1, 40 40 2)',
'LINESTRING Z(30 10 0, 10 30 1, 40 40 2)',
'LINESTRINGZ(30 10 0, 10 30 1, 40 40 2)',
'POLYGON Z ((30 10 0, 40 40 2, 20 40 1, 10 20 2, 30 10 0))',
'POLYGON Z((30 10 0, 40 40 2, 20 40 1, 10 20 2, 30 10 0))',
'POLYGONZ((30 10 0, 40 40 2, 20 40 1, 10 20 2, 30 10 0))',
);
foreach($zWktArray as $wkt) {
$checked = lizmapWkt::check($wkt);
$this->assertIsArray($checked, 'The '.$wkt.' has not been checked!');
$this->assertArrayHasKey('geomType', $checked);
$this->assertArrayHasKey('dim', $checked);
$this->assertEquals('z', $checked['dim']);
$this->assertArrayHasKey('str', $checked);
}

$notWktArray = array(
Expand All @@ -41,6 +66,35 @@ function testChecking() {
}
}

function testFixing() {
// Unfixed WKT
$wkt = 'POINT (30 10)';
$nWkt = lizmapWkt::fix($wkt);
$this->assertEquals($wkt, $nWkt);

$wkt = 'POINT Z (30 10 0)';
$nWkt = lizmapWkt::fix($wkt);
$this->assertEquals($wkt, $nWkt);

$wkt = 'POINT M (30 10 0)';
$nWkt = lizmapWkt::fix($wkt);
$this->assertEquals($wkt, $nWkt);

$wkt = 'POINT ZM (30 10 0 0)';
$nWkt = lizmapWkt::fix($wkt);
$this->assertEquals($wkt, $nWkt);

// Fixed WKT
$expectedWkt = 'POINT Z (30 10 0)';
$wkt = 'POINT Z(30 10 0)';
$nWkt = lizmapWkt::fix($wkt);
$this->assertEquals($expectedWkt, $nWkt);

$wkt = 'POINTZ(30 10 0)';
$nWkt = lizmapWkt::fix($wkt);
$this->assertEquals($expectedWkt, $nWkt);
}

function testPoint() {
$wkt = 'POINT (30 10)';
$geom = lizmapWkt::parse($wkt);
Expand Down

0 comments on commit 9ef5e7a

Please sign in to comment.