Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions i18n/qqq.json
Original file line number Diff line number Diff line change
Expand Up @@ -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<code>$1</code> 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}}",
Expand Down
36 changes: 36 additions & 0 deletions src/Map/SemanticFormat/MapPrinter.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'];
}

Expand All @@ -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(),
Expand Down
88 changes: 88 additions & 0 deletions tests/System/SemanticQueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
*/
class SemanticQueryTest extends TestCase {

private const MISSING_COORDINATES_WARNING = 'none of the properties used in the query';

/**
* @var PageCreator
*/
Expand Down Expand Up @@ -122,4 +124,90 @@ public function testMapQueryWithTemplate() {
$this->assertStringContainsString( '<div id="map_', $content );
}

public function testQueryWithoutCoordinatePrintoutShowsTypeWarning() {
$this->pageCreator->createPage(
'Property:TextualCoordinates',
'[[Has type::Text]]'
);

$this->pageCreator->createPage(
'TextualCoordinatesPage',
'[[TextualCoordinates::52° 31\' 0", 13° 24\' 0"]]'
);

$content = $this->getResultForQuery( '{{#ask:[[TextualCoordinates::+]]|?TextualCoordinates|format=map}}' );

$this->assertStringNotContainsString( '<div id="map_', $content );
$this->assertStringContainsString( self::MISSING_COORDINATES_WARNING, $content );
}

public function testQueryWithCoordinatePrintoutWithoutValuesShowsNoWarning() {
$this->createDataPages();

$this->pageCreator->createPage(
'PageWithoutCoordinates',
'[[Description::A page without coordinates]]'
);

$content = $this->getResultForQuery( '{{#ask:[[Description::A page without coordinates]]|?Coordinates|format=map}}' );

$this->assertStringNotContainsString( '<div id="map_', $content );
$this->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( '<div id="map_', $content );
$this->assertStringNotContainsString( self::MISSING_COORDINATES_WARNING, $content );
}

public function testHalfConfiguredAjaxQueryWithoutCoordinatePrintoutShowsWarning() {
$this->createDataPages();

// The ajax JS only activates when both ajaxcoordproperty and ajaxquery are set,
// so setting only one of them never loads markers and the warning still applies.
$content = $this->getResultForQuery( '{{#ask:[[Description::+]]|?Description|format=map|ajaxcoordproperty=Coordinates}}' );

$this->assertStringContainsString( self::MISSING_COORDINATES_WARNING, $content );
}

public function testGeoJsonQueryWithoutCoordinatePrintoutShowsNoWarning() {
$this->createDataPages();

$content = $this->getResultForQuery( '{{#ask:[[Description::+]]|?Description|format=leaflet|geojson=TestGeoJson}}' );

$this->assertStringNotContainsString( self::MISSING_COORDINATES_WARNING, $content );
}

public function testGoogleMaps3KmlQueryWithoutCoordinatePrintoutShowsNoWarning() {
$this->createDataPages();

$content = $this->getResultForQuery( '{{#ask:[[Description::+]]|?Description|format=googlemaps3|kml=TestFile.kml}}' );

$this->assertStringNotContainsString( self::MISSING_COORDINATES_WARNING, $content );
}

public function testQueryWithRecordPrintoutShowsNoWarning() {
$this->createDataPages();

$this->pageCreator->createPage(
'Property:AddressRecord',
'[[Has type::Record]] [[Has fields::Description;Coordinates]]'
);

$this->pageCreator->createPage(
'PageWithRecordProperty',
'[[Description::Tagged for the record printout test]]'
);

$content = $this->getResultForQuery( '{{#ask:[[Description::Tagged for the record printout test]]|?AddressRecord|format=map}}' );

$this->assertStringNotContainsString( self::MISSING_COORDINATES_WARNING, $content );
}

}
Loading