From 4981e7799ae522712bd7f62676fc5763c7998788 Mon Sep 17 00:00:00 2001 From: Jeroen De Dauw Date: Thu, 2 Jul 2026 16:20:59 +0200 Subject: [PATCH] Warn when a semantic map query has no coordinate printout For https://github.com/ProfessionalWiki/Maps/issues/917 When an #ask query with a map format returns results but none of the queried properties can provide coordinates, the map printer rendered nothing (the empty "default" parameter), leaving no hint about why the map is missing. This commonly happens when a property is unintentionally typed Text, for instance via a stale vocabulary import mapping schema:geo to Type:Text (as shipped by Semantic MediaWiki before version 5.0). The printer now adds a query error, rendered through Semantic MediaWiki's standard warning mechanism, explaining that none of the queried properties has the "Geographic coordinates" type. The warning is suppressed for queries that get their markers elsewhere: a fully configured ajaxcoordproperty/ajaxquery pair, geojson, or GoogleMaps3's kml/gkml, and for record printouts (records can contain coordinate fields). Queries that do have a coordinate printout but no values keep the existing silent behavior. Co-Authored-By: Claude Fable 5 --- i18n/en.json | 1 + i18n/qqq.json | 1 + src/Map/SemanticFormat/MapPrinter.php | 36 +++++++++++ tests/System/SemanticQueryTest.php | 88 +++++++++++++++++++++++++++ 4 files changed, 126 insertions(+) diff --git a/i18n/en.json b/i18n/en.json index 3004c4d2..3ef7de24 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -151,6 +151,7 @@ "maps-googlemaps3-par-clusteraveragecenter": "Whether the center of each cluster should be the average of all markers in the cluster.", "maps-googlemaps3-par-clusterminsize": "The minimum number of markers to be in a cluster before the markers are hidden and a count is shown.", "semanticmaps-unrecognizeddistance": "The value $1 is not a valid distance.", + "semanticmaps-no-coordinate-printout": "The map cannot show any locations, because none of the properties used in the query is of type \"Geographic coordinates\".", "semanticmaps-kml-link": "View the KML file", "semanticmaps-kml": "KML", "semanticmaps-default-kml-pagelink": "View page $1", diff --git a/i18n/qqq.json b/i18n/qqq.json index 55c705c6..ab4c9f9f 100644 --- a/i18n/qqq.json +++ b/i18n/qqq.json @@ -162,6 +162,7 @@ "maps-googlemaps3-par-clusteraveragecenter": "{{maps-par|googlemaps3|clusteraveragecenter}}", "maps-googlemaps3-par-clusterminsize": "{{maps-par|googlemaps3|clusterminsize}}", "semanticmaps-unrecognizeddistance": "This is an error message.\n\nParameter:\n* $1 - distance", + "semanticmaps-no-coordinate-printout": "Warning shown when a semantic query with a map result format returns results, but none of the queried properties is of the \"Geographic coordinates\" datatype, so the map has no locations to show. \"Geographic coordinates\" is the English name of the Semantic MediaWiki datatype.", "semanticmaps-kml-link": "This is the label of a link.", "semanticmaps-kml": "{{optional}}", "semanticmaps-default-kml-pagelink": "Used as default value for \"pagelinktext\" input box.\nSee example: [{{canonicalurl:Special:Ask|format=kml}} Special:Ask]\n\n$1 is not a parameter (appears as is), but it will be replaced by the page title.\n\nSee also:\n* {{msg-mw|Semanticmaps-kml-pagelinktext}}\n{{Identical|View page}}", diff --git a/src/Map/SemanticFormat/MapPrinter.php b/src/Map/SemanticFormat/MapPrinter.php index 6f04bf69..8c4b2636 100644 --- a/src/Map/SemanticFormat/MapPrinter.php +++ b/src/Map/SemanticFormat/MapPrinter.php @@ -118,6 +118,10 @@ final public function getResultText( QueryResult $res, $outputMode ): string { $params['ajaxquery'] = urlencode( $params['ajaxquery'] ); if ( $params['locations'] === [] ) { + if ( $this->shouldWarnAboutMissingCoordinatePrintout( $res, $params ) ) { + $res->addErrors( [ wfMessage( 'semanticmaps-no-coordinate-printout' )->inContentLanguage()->text() ] ); + } + return $params['default']; } @@ -139,6 +143,38 @@ final public function getResultText( QueryResult $res, $outputMode ): string { return $mapOutput->getHtml(); } + private function shouldWarnAboutMissingCoordinatePrintout( QueryResult $res, array $params ): bool { + return !$this->hasAlternateMarkerSource( $params ) + && !$this->queryHasCoordinatePrintout( $res ); + } + + private function hasAlternateMarkerSource( array $params ): bool { + return $this->hasAjaxCoordinateSource( $params ) + || ( $params['geojson'] ?? '' ) !== '' + || ( $params['kml'] ?? [] ) !== [] + || ( $params['gkml'] ?? [] ) !== []; + } + + private function hasAjaxCoordinateSource( array $params ): bool { + // The JS only loads markers via ajax when both parameters are set; a + // half-configured pair never fires ajax, so the warning still applies. + return $params['ajaxcoordproperty'] !== '' && $params['ajaxquery'] !== ''; + } + + private function queryHasCoordinatePrintout( QueryResult $res ): bool { + foreach ( $res->getPrintRequests() as $printRequest ) { + // Approximation: any Record printout is treated as coordinate-capable + // without checking whether its declared fields actually include one. + // See QueryHandler::getLocationsAndProperties for the precise, + // per-value check this mirrors at the print-request-type level. + if ( in_array( $printRequest->getTypeID(), [ '_geo', '_rec' ], true ) ) { + return true; + } + } + + return false; + } + private function outputResources( MapOutput $mapOutput ) { SMWOutputs::requireHeadItem( $this->randomString(), diff --git a/tests/System/SemanticQueryTest.php b/tests/System/SemanticQueryTest.php index 2a65b485..28cacda6 100644 --- a/tests/System/SemanticQueryTest.php +++ b/tests/System/SemanticQueryTest.php @@ -20,6 +20,8 @@ */ class SemanticQueryTest extends TestCase { + private const MISSING_COORDINATES_WARNING = 'none of the properties used in the query'; + /** * @var PageCreator */ @@ -122,4 +124,90 @@ public function testMapQueryWithTemplate() { $this->assertStringContainsString( '
getResultForQuery( '{{#ask:[[TextualCoordinates::+]]|?TextualCoordinates|format=map}}' ); + + $this->assertStringNotContainsString( '
assertStringNotContainsString( self::MISSING_COORDINATES_WARNING, $content ); + } + + public function testAjaxQueryWithoutCoordinatePrintoutShowsNoWarning() { + $this->createDataPages(); + + $content = $this->getResultForQuery( + '{{#ask:[[Description::+]]|?Description|format=map|ajaxcoordproperty=Coordinates|ajaxquery=TestQuery}}' + ); + + $this->assertStringNotContainsString( '