diff options
Diffstat (limited to 'www/wiki/extensions/Maps/src')
23 files changed, 684 insertions, 290 deletions
diff --git a/www/wiki/extensions/Maps/src/DataAccess/GeoJsonFetcher.php b/www/wiki/extensions/Maps/src/DataAccess/GeoJsonFetcher.php new file mode 100644 index 00000000..ea7724d5 --- /dev/null +++ b/www/wiki/extensions/Maps/src/DataAccess/GeoJsonFetcher.php @@ -0,0 +1,93 @@ +<?php + +declare( strict_types = 1 ); + +namespace Maps\DataAccess; + +use FileFetcher\FileFetcher; +use FileFetcher\FileFetchingException; +use MediaWiki\Storage\RevisionLookup; + +/** + * Returns the content of the JSON file at the specified location as array. + * Empty array is returned on failure. + * + * @licence GNU GPL v2+ + * @author Jeroen De Dauw < jeroendedauw@gmail.com > + */ +class GeoJsonFetcher { + + private $fileFetcher; + private $titleParser; + private $revisionLookup; + + public function __construct( FileFetcher $fileFetcher, \TitleParser $titleParser, RevisionLookup $revisionLookup ) { + $this->fileFetcher = $fileFetcher; + $this->titleParser = $titleParser; + $this->revisionLookup = $revisionLookup; + } + + public function parse( string $fileLocation ): array { + return $this->fetch( $fileLocation )->getContent(); + } + + public function fetch( string $fileLocation ) { + try { + $title = $this->titleParser->parseTitle( $fileLocation, NS_GEO_JSON ); + $revision = $this->revisionLookup->getRevisionByTitle( $title ); + + if ( $revision !== null ) { + $content = $revision->getContent( 'main' ); + + if ( $content instanceof \JsonContent ) { + return new GeoJsonFetcherResult( + $this->normalizeJson( $content->getNativeData() ), + $revision->getId(), + $title + ); + } + } + } + catch ( \MalformedTitleException $e ) { + } + + // Prevent reading JSON files on the server + if( !filter_var( $fileLocation, FILTER_VALIDATE_URL) ) { + return $this->newEmptyResult(); + } + + try { + return new GeoJsonFetcherResult( + $this->normalizeJson( $this->fileFetcher->fetchFile( $fileLocation ) ), + null, + null + ); + } + catch ( FileFetchingException $ex ) { + return $this->newEmptyResult(); + } + } + + private function newEmptyResult(): GeoJsonFetcherResult { + return new GeoJsonFetcherResult( + [], + null, + null + ); + } + + private function normalizeJson( ?string $jsonString ): array { + if ( $jsonString === null ) { + return []; + } + + $json = json_decode( $jsonString, true ); + + if ( $json === null ) { + return []; + } + + return $json; + } + +} diff --git a/www/wiki/extensions/Maps/src/DataAccess/GeoJsonFetcherResult.php b/www/wiki/extensions/Maps/src/DataAccess/GeoJsonFetcherResult.php new file mode 100644 index 00000000..7345b649 --- /dev/null +++ b/www/wiki/extensions/Maps/src/DataAccess/GeoJsonFetcherResult.php @@ -0,0 +1,31 @@ +<?php + +declare( strict_types = 1 ); + +namespace Maps\DataAccess; + +class GeoJsonFetcherResult { + + private $content; + private $revisionId; + private $source; + + public function __construct( array $content, ?int $revisionId, ?\TitleValue $source ) { + $this->content = $content; + $this->revisionId = $revisionId; + $this->source = $source; + } + + public function getContent(): array { + return $this->content; + } + + public function getTitleValue(): ?\TitleValue { + return $this->source; + } + + public function getRevisionId(): ?int { + return $this->revisionId; + } + +} diff --git a/www/wiki/extensions/Maps/src/DataAccess/JsonFileParser.php b/www/wiki/extensions/Maps/src/DataAccess/JsonFileParser.php deleted file mode 100644 index 81d6cfa0..00000000 --- a/www/wiki/extensions/Maps/src/DataAccess/JsonFileParser.php +++ /dev/null @@ -1,79 +0,0 @@ -<?php - -declare( strict_types = 1 ); - -namespace Maps\DataAccess; - -use FileFetcher\FileFetcher; -use FileFetcher\FileFetchingException; -use Maps\MapsFactory; -use ValueParsers\ParseException; -use ValueParsers\ValueParser; - -/** - * Returns the content of the JSON file at the specified location as array. - * Empty array is returned on failure. - * - * @licence GNU GPL v2+ - * @author Jeroen De Dauw < jeroendedauw@gmail.com > - */ -class JsonFileParser implements ValueParser { - - private $fileFetcher; - private $pageContentFetcher; - private $defaultNamespace; - - public function __construct( $fileFetcher = null, PageContentFetcher $pageContentFetcher = null ) { - $this->fileFetcher = $fileFetcher instanceof FileFetcher - ? $fileFetcher : MapsFactory::newDefault()->getGeoJsonFileFetcher(); - - $this->pageContentFetcher = $pageContentFetcher instanceof PageContentFetcher - ? $pageContentFetcher : MapsFactory::newDefault()->getPageContentFetcher(); - - $this->defaultNamespace = NS_GEO_JSON; - } - - /** - * @param string $fileLocation - * - * @return array - * @throws ParseException - */ - public function parse( $fileLocation ) { - $jsonString = $this->getJsonString( $fileLocation ); - - if ( $jsonString === null ) { - return []; - } - - $json = json_decode( $jsonString, true ); - - if ( $json === null ) { - return []; - } - - return $json; - } - - private function getJsonString( string $fileLocation ): ?string { - $content = $this->pageContentFetcher->getPageContent( $fileLocation, $this->defaultNamespace ); - - if ( $content instanceof \JsonContent ) { - return $content->getNativeData(); - } - - // Prevent reading JSON files on the server - if( !filter_var( $fileLocation, FILTER_VALIDATE_URL) ) { - return null; - } - - try { - return $this->fileFetcher->fetchFile( $fileLocation ); - } - catch ( FileFetchingException $ex ) { - return null; - } - } - - -} diff --git a/www/wiki/extensions/Maps/src/GoogleMapsService.php b/www/wiki/extensions/Maps/src/GoogleMapsService.php index 9c1b91b9..b1ccba34 100644 --- a/www/wiki/extensions/Maps/src/GoogleMapsService.php +++ b/www/wiki/extensions/Maps/src/GoogleMapsService.php @@ -3,6 +3,8 @@ namespace Maps; use Html; +use ParamProcessor\ProcessedParam; +use ParamProcessor\ProcessingResult; /** * @licence GNU GPL v2+ @@ -49,7 +51,19 @@ class GoogleMapsService implements MappingService { global $egMapsGMaps3DefTypeStyle, $egMapsGMaps3DefZoomStyle, $egMapsGMaps3AutoInfoWindows; global $egMapsResizableByDefault; - $params = []; + $params = MapsFunctions::getCommonParameters(); + + $params['visitedicon'] = [ + 'default' => '', + 'message' => 'maps-displaymap-par-visitedicon', + ]; + + $params['wmsoverlay'] = [ + 'type' => 'wmsoverlay', + 'default' => false, + 'delimiter' => ' ', + 'message' => 'maps-displaymap-par-wmsoverlay', + ]; $params['zoom'] = [ 'type' => 'integer', @@ -150,7 +164,8 @@ class GoogleMapsService implements MappingService { 'message' => 'maps-googlemaps3-par-poi', ]; - $params['markercluster'] = [ + $params['cluster'] = [ + 'aliases' => [ 'markercluster' ], 'type' => 'boolean', 'default' => false, 'message' => 'maps-par-markercluster', @@ -199,11 +214,18 @@ class GoogleMapsService implements MappingService { 'message' => 'maps-par-kml', 'islist' => true, 'post-format' => function( array $kmlFileNames ) { - return array_map( - function( string $fileName ) { - return wfExpandUrl( MapsFunctions::getFileUrl( $fileName ) ); - }, - $kmlFileNames + return array_values( + array_filter( + array_map( + function( string $fileName ) { + return wfExpandUrl( MapsFunctions::getFileUrl( $fileName ) ); + }, + $kmlFileNames + ), + function( string $fileName ) { + return $fileName !== ''; + } + ) ); } ]; @@ -220,13 +242,15 @@ class GoogleMapsService implements MappingService { // new CriterionSearchMarkers() FIXME ]; - $params['enablefullscreen'] = [ + $params['fullscreen'] = [ + 'aliases' => [ 'enablefullscreen' ], 'type' => 'boolean', 'default' => false, 'message' => 'maps-par-enable-fullscreen', ]; $params['scrollwheelzoom'] = [ + 'aliases' => [ 'scrollzoom' ], 'type' => 'boolean', 'default' => false, 'message' => 'maps-par-scrollwheelzoom', @@ -251,7 +275,7 @@ class GoogleMapsService implements MappingService { } public function getResourceModules(): array { - return [ 'ext.maps.googlemaps3', 'ext.sm.googlemaps3ajax' ]; + return [ 'ext.maps.googlemaps3', 'ext.maps.googlemaps3ajax' ]; } public static function getApiScript( $langCode, array $urlArgs = [] ) { @@ -311,4 +335,33 @@ class GoogleMapsService implements MappingService { ) ]; } + + public function processingResultToMapParams( ProcessingResult $processingResult ): array { + $parameters = $processingResult->getParameters(); + + if ( array_key_exists( 'zoom', $parameters ) && $parameters['zoom']->wasSetToDefault() && count( + $parameters['coordinates']->getValue() + ) > 1 ) { + $parameters['zoom'] = $this->getParameterWithValue( $parameters['zoom'], false ); + } + + $mapParams = []; + + foreach ( $parameters as $parameter ) { + $mapParams[$parameter->getName()] = $parameter->getValue(); + } + + return $mapParams; + } + + private function getParameterWithValue( ProcessedParam $param, $value ) { + return new ProcessedParam( + $param->getName(), + $value, + $param->wasSetToDefault(), + $param->getOriginalName(), + $param->getOriginalValue() + ); + } + } diff --git a/www/wiki/extensions/Maps/src/LeafletService.php b/www/wiki/extensions/Maps/src/LeafletService.php index 0e41d670..6d189fdb 100644 --- a/www/wiki/extensions/Maps/src/LeafletService.php +++ b/www/wiki/extensions/Maps/src/LeafletService.php @@ -3,6 +3,8 @@ namespace Maps; use Html; +use ParamProcessor\ParameterTypes; +use ParamProcessor\ProcessingResult; /** * @licence GNU GPL v2+ @@ -24,19 +26,17 @@ class LeafletService implements MappingService { } public function getParameterInfo(): array { - global $GLOBALS; - - $params = []; + $params = MapsFunctions::getCommonParameters(); $params['zoom'] = [ - 'type' => 'integer', + 'type' => ParameterTypes::INTEGER, 'range' => [ 0, 20 ], 'default' => false, 'message' => 'maps-par-zoom' ]; $params['defzoom'] = [ - 'type' => 'integer', + 'type' => ParameterTypes::INTEGER, 'range' => [ 0, 20 ], 'default' => self::getDefaultZoom(), 'message' => 'maps-leaflet-par-defzoom' @@ -51,8 +51,9 @@ class LeafletService implements MappingService { 'islist' => true, ]; - $params['overlaylayers'] = [ - 'type' => 'string', + $params['overlays'] = [ + 'aliases' => [ 'overlaylayers' ], + 'type' => ParameterTypes::STRING, 'values' => array_keys( $GLOBALS['egMapsLeafletAvailableOverlayLayers'], true, true ), 'default' => $GLOBALS['egMapsLeafletOverlayLayers'], 'message' => 'maps-leaflet-par-overlaylayers', @@ -60,59 +61,68 @@ class LeafletService implements MappingService { ]; $params['resizable'] = [ - 'type' => 'boolean', + 'type' => ParameterTypes::BOOLEAN, 'default' => $GLOBALS['egMapsResizableByDefault'], 'message' => 'maps-par-resizable' ]; - $params['enablefullscreen'] = [ - 'type' => 'boolean', + $params['fullscreen'] = [ + 'aliases' => [ 'enablefullscreen' ], + 'type' => ParameterTypes::BOOLEAN, 'default' => false, 'message' => 'maps-par-enable-fullscreen', ]; $params['scrollwheelzoom'] = [ - 'type' => 'boolean', + 'aliases' => [ 'scrollzoom' ], + 'type' => ParameterTypes::BOOLEAN, 'default' => true, 'message' => 'maps-par-scrollwheelzoom', ]; - $params['markercluster'] = [ - 'type' => 'boolean', + $params['cluster'] = [ + 'aliases' => [ 'markercluster' ], + 'type' => ParameterTypes::BOOLEAN, 'default' => false, 'message' => 'maps-par-markercluster', ]; $params['clustermaxzoom'] = [ - 'type' => 'integer', + 'type' => ParameterTypes::INTEGER, 'default' => 20, 'message' => 'maps-par-clustermaxzoom', ]; $params['clusterzoomonclick'] = [ - 'type' => 'boolean', + 'type' => ParameterTypes::BOOLEAN, 'default' => true, 'message' => 'maps-par-clusterzoomonclick', ]; $params['clustermaxradius'] = [ - 'type' => 'integer', + 'type' => ParameterTypes::INTEGER, 'default' => 80, 'message' => 'maps-par-maxclusterradius', ]; $params['clusterspiderfy'] = [ - 'type' => 'boolean', + 'type' => ParameterTypes::BOOLEAN, 'default' => true, 'message' => 'maps-leaflet-par-clusterspiderfy', ]; $params['geojson'] = [ - 'type' => 'jsonfile', + 'type' => ParameterTypes::STRING, 'default' => '', 'message' => 'maps-displaymap-par-geojson', ]; + $params['clicktarget'] = [ + 'type' => ParameterTypes::STRING, + 'default' => '', + 'message' => 'maps-leaflet-par-clicktarget', + ]; + return $params; } @@ -132,7 +142,7 @@ class LeafletService implements MappingService { } public function getResourceModules(): array { - return [ 'ext.maps.leaflet', 'ext.sm.leafletajax' ]; + return [ 'ext.maps.leaflet.loader', 'ext.maps.leaflet.leafletajax' ]; } public function getDependencyHtml( array $params ): string { @@ -151,7 +161,7 @@ class LeafletService implements MappingService { } private function getDependencies( array $params ): array { - $leafletPath = $GLOBALS['wgScriptPath'] . '/extensions/Maps/resources/leaflet/leaflet'; + $leafletPath = $GLOBALS['wgScriptPath'] . '/extensions/Maps/resources/lib/leaflet'; return array_merge( [ @@ -181,4 +191,20 @@ class LeafletService implements MappingService { return array_unique( $layerDependencies ); } + public function processingResultToMapParams( ProcessingResult $processingResult ): array { + $mapParams = $processingResult->getParameterArray(); + + if ( $mapParams['geojson'] !== '' ) { + $fetcher = MapsFactory::newDefault()->newGeoJsonFetcher(); + + $result = $fetcher->fetch( $mapParams['geojson'] ); + + $mapParams['geojson'] = $result->getContent(); + $mapParams['GeoJsonSource'] = $result->getTitleValue() === null ? null : $result->getTitleValue()->getText(); + $mapParams['GeoJsonRevisionId'] = $result->getRevisionId(); + } + + return $mapParams; + } + } diff --git a/www/wiki/extensions/Maps/src/MappingService.php b/www/wiki/extensions/Maps/src/MappingService.php index 184ef712..960315d1 100644 --- a/www/wiki/extensions/Maps/src/MappingService.php +++ b/www/wiki/extensions/Maps/src/MappingService.php @@ -3,6 +3,8 @@ namespace Maps; use ParamProcessor\ParamDefinition; +use ParamProcessor\ProcessedParam; +use ParamProcessor\ProcessingResult; /** * @licence GNU GPL v2+ @@ -28,6 +30,8 @@ interface MappingService { */ public function getResourceModules(): array; - public function newMapId(); + public function newMapId(): string; + + public function processingResultToMapParams( ProcessingResult $processingResult ): array; } diff --git a/www/wiki/extensions/Maps/src/MapsFactory.php b/www/wiki/extensions/Maps/src/MapsFactory.php index 6ab23d5d..a8fd1338 100644 --- a/www/wiki/extensions/Maps/src/MapsFactory.php +++ b/www/wiki/extensions/Maps/src/MapsFactory.php @@ -4,6 +4,7 @@ declare( strict_types = 1 ); namespace Maps; +use DataValues\Geo\Parsers\LatLongParser; use FileFetcher\Cache\Factory as CacheFactory; use FileFetcher\FileFetcher; use Jeroen\SimpleGeocoder\Geocoder; @@ -13,13 +14,22 @@ use Jeroen\SimpleGeocoder\Geocoders\FileFetchers\GoogleGeocoder; use Jeroen\SimpleGeocoder\Geocoders\FileFetchers\NominatimGeocoder; use Jeroen\SimpleGeocoder\Geocoders\NullGeocoder; use Maps\DataAccess\CachingGeocoder; +use Maps\DataAccess\GeoJsonFetcher; use Maps\DataAccess\MapsFileFetcher; use Maps\DataAccess\MediaWikiFileUrlFinder; use Maps\DataAccess\PageContentFetcher; use Maps\MediaWiki\ParserHooks\DisplayMapFunction; use Maps\Presentation\CoordinateFormatter; +use Maps\Presentation\WikitextParsers\CircleParser; +use Maps\Presentation\WikitextParsers\DistanceParser; +use Maps\Presentation\WikitextParsers\ImageOverlayParser; +use Maps\Presentation\WikitextParsers\LineParser; use Maps\Presentation\WikitextParsers\LocationParser; +use Maps\Presentation\WikitextParsers\PolygonParser; +use Maps\Presentation\WikitextParsers\RectangleParser; +use Maps\Presentation\WikitextParsers\WmsOverlayParser; use MediaWiki\MediaWikiServices; +use ParamProcessor\ParamDefinitionFactory; use SimpleCache\Cache\Cache; use SimpleCache\Cache\MediaWikiCache; @@ -165,4 +175,28 @@ class MapsFactory { ); } + public function getParamDefinitionFactory(): ParamDefinitionFactory { + $factory = ParamDefinitionFactory::newDefault(); + + $factory->registerType( 'coordinate', [ 'string-parser' => LatLongParser::class ] ); + $factory->registerType( 'mapslocation', [ 'string-parser' => LocationParser::class ] ); + $factory->registerType( 'mapsline', [ 'string-parser' => LineParser::class ] ); + $factory->registerType( 'mapscircle', [ 'string-parser' => CircleParser::class ] ); + $factory->registerType( 'mapsrectangle', [ 'string-parser' => RectangleParser::class ] ); + $factory->registerType( 'mapspolygon', [ 'string-parser' => PolygonParser::class ] ); + $factory->registerType( 'distance', [ 'string-parser' => DistanceParser::class ] ); + $factory->registerType( 'wmsoverlay', [ 'string-parser' => WmsOverlayParser::class ] ); + $factory->registerType( 'mapsimageoverlay', [ 'string-parser' => ImageOverlayParser::class ] ); + + return $factory; + } + + public function newGeoJsonFetcher( FileFetcher $fileFetcher = null ): GeoJsonFetcher { + return new GeoJsonFetcher( + $fileFetcher ?? $this->getGeoJsonFileFetcher(), + $this->mediaWikiServices->getTitleParser(), + $this->mediaWikiServices->getRevisionLookup() + ); + } + } diff --git a/www/wiki/extensions/Maps/src/MapsFunctions.php b/www/wiki/extensions/Maps/src/MapsFunctions.php index 47cd1358..06274cc1 100644 --- a/www/wiki/extensions/Maps/src/MapsFunctions.php +++ b/www/wiki/extensions/Maps/src/MapsFunctions.php @@ -75,24 +75,19 @@ final class MapsFunctions { public static function getCommonParameters() { $params = []; - $params['mappingservice'] = [ - 'type' => 'string', - 'aliases' => 'service', - 'default' => $GLOBALS['egMapsDefaultService'], - 'values' => MapsFactory::globalInstance()->getMappingServices()->getAllNames(), - ]; - $params['width'] = [ 'type' => 'dimension', 'allowauto' => true, 'units' => [ 'px', 'ex', 'em', '%', '' ], 'default' => $GLOBALS['egMapsMapWidth'], + 'message' => 'maps-par-width', ]; $params['height'] = [ 'type' => 'dimension', 'units' => [ 'px', 'ex', 'em', '' ], 'default' => $GLOBALS['egMapsMapHeight'], + 'message' => 'maps-par-height', ]; $params['centre'] = [ @@ -100,16 +95,9 @@ final class MapsFunctions { 'aliases' => [ 'center' ], 'default' => false, 'manipulatedefault' => false, + 'message' => 'maps-par-centre', ]; - // Give grep a chance to find the usages: - // maps-par-mappingservice, maps-par-geoservice, maps-par-width, - // maps-par-height, maps-par-centre - foreach ( $params as $name => &$data ) { - $data['name'] = $name; - $data['message'] = 'maps-par-' . $name; - } - $params['title'] = [ 'name' => 'title', 'default' => $GLOBALS['egMapsDefaultTitle'], @@ -124,10 +112,6 @@ final class MapsFunctions { 'default' => '', ]; - $params['visitedicon'] = [ - 'default' => '', - ]; - $params['lines'] = [ 'type' => 'mapsline', 'default' => [], @@ -156,12 +140,6 @@ final class MapsFunctions { 'islist' => true, ]; - $params['wmsoverlay'] = [ - 'type' => 'wmsoverlay', - 'default' => false, - 'delimiter' => ' ', - ]; - $params['maxzoom'] = [ 'type' => 'integer', 'default' => false, @@ -188,8 +166,8 @@ final class MapsFunctions { // Give grep a chance to find the usages: // maps-displaymap-par-title, maps-displaymap-par-label, maps-displaymap-par-icon, - // maps-displaymap-par-visitedicon, aps-displaymap-par-lines, maps-displaymap-par-polygons, - // maps-displaymap-par-circles, maps-displaymap-par-rectangles, maps-displaymap-par-wmsoverlay, + // aps-displaymap-par-lines, maps-displaymap-par-polygons, + // maps-displaymap-par-circles, maps-displaymap-par-rectangles, // maps-displaymap-par-maxzoom, maps-displaymap-par-minzoom, maps-displaymap-par-copycoords, // maps-displaymap-par-static foreach ( $params as $name => &$param ) { diff --git a/www/wiki/extensions/Maps/src/MapsSetup.php b/www/wiki/extensions/Maps/src/MapsSetup.php index 245d3915..d682339b 100644 --- a/www/wiki/extensions/Maps/src/MapsSetup.php +++ b/www/wiki/extensions/Maps/src/MapsSetup.php @@ -5,7 +5,7 @@ declare( strict_types = 1 ); namespace Maps; use DataValues\Geo\Parsers\LatLongParser; -use Maps\DataAccess\JsonFileParser; +use Maps\DataAccess\GeoJsonFetcher; use Maps\MediaWiki\Content\GeoJsonContent; use Maps\MediaWiki\Content\GeoJsonContentHandler; use Maps\MediaWiki\ParserHooks\CoordinatesFunction; @@ -47,15 +47,6 @@ class MapsSetup { } } - private function registerAllTheThings() { - $this->registerParserHooks(); - $this->registerPermissions(); - $this->registerParameterTypes(); - $this->registerHooks(); - - $this->mwGlobals['wgContentHandlers'][GeoJsonContent::CONTENT_MODEL_ID] = GeoJsonContentHandler::class; - } - private function defaultSettings() { if ( $this->mwGlobals['egMapsGMaps3Language'] === '' ) { $this->mwGlobals['egMapsGMaps3Language'] = $this->mwGlobals['wgLang']; @@ -74,6 +65,15 @@ class MapsSetup { } } + private function registerAllTheThings() { + $this->registerParserHooks(); + $this->registerPermissions(); + $this->registerParameterTypes(); + $this->registerHooks(); + $this->registerGeoJsonContentModel(); + $this->registerEditApiModuleFallbacks(); + } + private function registerParserHooks() { if ( $this->mwGlobals['egMapsEnableCoordinateFunction'] ) { $this->mwGlobals['wgHooks']['ParserFirstCallInit'][] = function ( Parser &$parser ) { @@ -109,13 +109,7 @@ class MapsSetup { $hookName, function ( $text, array $arguments, Parser $parser ) { if ( $text !== null ) { - $defaultParameters = DisplayMapFunction::getHookDefinition( "\n" )->getDefaultParameters(); - $defaultParam = array_shift( $defaultParameters ); - - // If there is a first default parameter, set the tag contents as its value. - if ( $defaultParam !== null ) { - $arguments[$defaultParam] = $text; - } + $arguments[DisplayMapFunction::getDefaultParameters()[0]] = $text; } return MapsFactory::newDefault()->getDisplayMapFunction()->getMapHtmlForParameterList( $parser, $arguments ); @@ -192,15 +186,66 @@ class MapsSetup { $this->mwGlobals['wgParamDefinitions']['mapsimageoverlay'] = [ 'string-parser' => ImageOverlayParser::class, ]; - - $this->mwGlobals['wgParamDefinitions']['jsonfile'] = [ - 'string-parser' => JsonFileParser::class, - ]; } private function registerHooks() { $this->mwGlobals['wgHooks']['AdminLinks'][] = 'Maps\MediaWiki\MapsHooks::addToAdminLinks'; $this->mwGlobals['wgHooks']['MakeGlobalVariablesScript'][] = 'Maps\MediaWiki\MapsHooks::onMakeGlobalVariablesScript'; + $this->mwGlobals['wgHooks']['SkinTemplateNavigation'][] = 'Maps\MediaWiki\MapsHooks::onSkinTemplateNavigation'; + $this->mwGlobals['wgHooks']['BeforeDisplayNoArticleText'][] = 'Maps\MediaWiki\MapsHooks::onBeforeDisplayNoArticleText'; + $this->mwGlobals['wgHooks']['ShowMissingArticle'][] = 'Maps\MediaWiki\MapsHooks::onShowMissingArticle'; + $this->mwGlobals['wgHooks']['ListDefinedTags'][] = 'Maps\MediaWiki\MapsHooks::onRegisterTags'; + $this->mwGlobals['wgHooks']['ChangeTagsListActive'][] = 'Maps\MediaWiki\MapsHooks::onRegisterTags'; + $this->mwGlobals['wgHooks']['ChangeTagsAllowedAdd'][] = 'Maps\MediaWiki\MapsHooks::onChangeTagsAllowedAdd'; + $this->mwGlobals['wgHooks']['ResourceLoaderTestModules'][] = 'Maps\MediaWiki\MapsHooks::onResourceLoaderTestModules'; + } + + private function registerGeoJsonContentModel() { + $this->mwGlobals['wgContentHandlers'][GeoJsonContent::CONTENT_MODEL_ID] = GeoJsonContentHandler::class; + } + + private function registerEditApiModuleFallbacks() { + // mediawiki.api.edit is present in 1.31 but not 1.32 + // Once Maps requires MW 1.32+, this can be removed after replacing usage of mediawiki.api.edit + if ( version_compare( $this->mwGlobals['wgVersion'], '1.32', '>=' ) ) { + $this->mwGlobals['wgResourceModules']['mediawiki.api.edit'] = [ + 'dependencies' => [ + 'mediawiki.api' + ], + 'targets' => [ 'desktop', 'mobile' ] + ]; + } + + // 1.35 combines the jquery.ui modules into one + if ( version_compare( $this->mwGlobals['wgVersion'], '1.35', '>=' ) ) { + $this->mwGlobals['wgResourceModules']['jquery.ui.resizable'] = [ + 'dependencies' => [ + 'jquery.ui' + ], + 'targets' => [ 'desktop', 'mobile' ] + ]; + + $this->mwGlobals['wgResourceModules']['jquery.ui.autocomplete'] = [ + 'dependencies' => [ + 'jquery.ui' + ], + 'targets' => [ 'desktop', 'mobile' ] + ]; + + $this->mwGlobals['wgResourceModules']['jquery.ui.slider'] = [ + 'dependencies' => [ + 'jquery.ui' + ], + 'targets' => [ 'desktop', 'mobile' ] + ]; + + $this->mwGlobals['wgResourceModules']['jquery.ui.dialog'] = [ + 'dependencies' => [ + 'jquery.ui' + ], + 'targets' => [ 'desktop', 'mobile' ] + ]; + } } } diff --git a/www/wiki/extensions/Maps/src/MediaWiki/Content/GeoJsonContent.php b/www/wiki/extensions/Maps/src/MediaWiki/Content/GeoJsonContent.php index 72a89b04..c6eaae23 100644 --- a/www/wiki/extensions/Maps/src/MediaWiki/Content/GeoJsonContent.php +++ b/www/wiki/extensions/Maps/src/MediaWiki/Content/GeoJsonContent.php @@ -2,48 +2,55 @@ namespace Maps\MediaWiki\Content; -use Html; +use FormatJson; +use Maps\Presentation\GeoJsonMapPageUi; +use Maps\Presentation\OutputFacade; use ParserOptions; use ParserOutput; +use Status; use Title; class GeoJsonContent extends \JsonContent { public const CONTENT_MODEL_ID = 'GeoJSON'; + public static function newEmptyContentString(): string { + $text = '{"type": "FeatureCollection", "features": []}'; + return FormatJson::encode( FormatJson::parse( $text )->getValue(), true, FormatJson::UTF8_OK ); + } + public function __construct( string $text, string $modelId = self::CONTENT_MODEL_ID ) { - parent::__construct( $text, $modelId ); + parent::__construct( + $text, + $modelId + ); + } + + public function getData(): Status { + $status = parent::getData(); + + if ( $status->isGood() && !$this->isGeoJson( $status->getValue() ) ) { + return Status::newFatal( 'Invalid GeoJson' ); + } + + return $status; + } + + private function isGeoJson( $json ): bool { + return property_exists( $json, 'type' ) + && $json->type === 'FeatureCollection' + && property_exists( $json, 'features' ) + && is_array( $json->features ); } protected function fillParserOutput( Title $title, $revId, ParserOptions $options, $generateHtml, ParserOutput &$output ) { if ( $generateHtml && $this->isValid() ) { - $output->setText( $this->getMapHtml( $this->beautifyJSON() ) ); - $output->addModules( 'ext.maps.leaflet.editor' ); + ( GeoJsonMapPageUi::forExistingPage( $this->beautifyJSON() ) )->addToOutput( OutputFacade::newFromParserOutput( $output ) ); } else { $output->setText( '' ); } } - private function getMapHtml( string $jsonString ): string { - return - Html::element( - 'div', - [ - 'id' => 'GeoJsonMap', - 'class' => 'GeoJsonMap', - ] - ) - . '<style>' - . '.GeoJsonMap {width: "100%"; height: 600px; display: "inline-block"}' - . '</style>' - . - Html::element( - 'script', - [], - 'var GeoJson =' . $jsonString . ';' - ); - } - -}
\ No newline at end of file +} diff --git a/www/wiki/extensions/Maps/src/MediaWiki/Content/GeoJsonContentHandler.php b/www/wiki/extensions/Maps/src/MediaWiki/Content/GeoJsonContentHandler.php index b192a9c3..de6c38b1 100644 --- a/www/wiki/extensions/Maps/src/MediaWiki/Content/GeoJsonContentHandler.php +++ b/www/wiki/extensions/Maps/src/MediaWiki/Content/GeoJsonContentHandler.php @@ -12,4 +12,8 @@ class GeoJsonContentHandler extends \JsonContentHandler { return GeoJsonContent::class; } -}
\ No newline at end of file + public function makeEmptyContent() { + return new GeoJsonContent( GeoJsonContent::newEmptyContentString() ); + } + +} diff --git a/www/wiki/extensions/Maps/src/MediaWiki/MapsHooks.php b/www/wiki/extensions/Maps/src/MediaWiki/MapsHooks.php index e2a8ad95..9cefac2d 100644 --- a/www/wiki/extensions/Maps/src/MediaWiki/MapsHooks.php +++ b/www/wiki/extensions/Maps/src/MediaWiki/MapsHooks.php @@ -1,9 +1,13 @@ <?php + namespace Maps\MediaWiki; use AlItem; use ALTree; +use Maps\Presentation\GeoJsonNewPageUi; +use Maps\Presentation\OutputFacade; +use SkinTemplate; /** * Static class for hooks handled by the Maps extension. @@ -59,10 +63,67 @@ final class MapsHooks { $vars['egMapsDebugJS'] = $GLOBALS['egMapsDebugJS']; $vars['egMapsAvailableServices'] = $GLOBALS['egMapsAvailableServices']; $vars['egMapsLeafletLayersApiKeys'] = $GLOBALS['egMapsLeafletLayersApiKeys']; + $vars['egMapsLeafletLayersDark'] = $GLOBALS['egMapsLeafletLayersDark']; $vars += $GLOBALS['egMapsGlobalJSVars']; return true; } + public static function onSkinTemplateNavigation( SkinTemplate $skinTemplate, array &$links ) { + if ( $skinTemplate->getTitle() === null ) { + return true; + } + + if ( $skinTemplate->getTitle()->getNamespace() === NS_GEO_JSON ) { + if ( array_key_exists( 'edit', $links['views'] ) ) { + $links['views']['edit']['text'] = wfMessage( + $skinTemplate->getTitle()->exists() ? 'maps-geo-json-edit-source': 'maps-geo-json-create-source' + ); + } + } + + return true; + } + + public static function onBeforeDisplayNoArticleText( \Article $article ) { + return !self::shouldShowGeoJsonCreatePageUi( $article ); + } + + public static function onShowMissingArticle( \Article $article ) { + if ( self::shouldShowGeoJsonCreatePageUi( $article ) ) { + $ui = new GeoJsonNewPageUi( OutputFacade::newFromOutputPage( $article->getContext()->getOutput() ) ); + $ui->addToOutput(); + } + + return true; + } + + private static function shouldShowGeoJsonCreatePageUi( \Article $article ): bool { + return $article->getTitle()->getNamespace() === NS_GEO_JSON + && $article->getContext()->getUser()->isAllowed( 'createpage' ); + } + + public static function onRegisterTags( array &$tags ) { + $tags[] = 'maps-visual-edit'; + return true; + } + + public static function onChangeTagsAllowedAdd( array &$allowedTags, array $tags, \User $user = null ) { + $allowedTags[] = 'maps-visual-edit'; + } + + public static function onResourceLoaderTestModules( array &$modules, $resourceLoader ) { + $modules['qunit']['ext.maps.test'] = [ + 'scripts' => [ + 'tests/js/leaflet/GeoJsonTest.js', + ], + 'dependencies' => [ + 'ext.maps.leaflet.geojson', + ], + 'localBasePath' => __DIR__ . '/../../', + 'remoteExtPath' => 'Maps' + ]; + } + } diff --git a/www/wiki/extensions/Maps/src/MediaWiki/ParserHooks/DisplayMapFunction.php b/www/wiki/extensions/Maps/src/MediaWiki/ParserHooks/DisplayMapFunction.php index bad0d842..5d64b52e 100644 --- a/www/wiki/extensions/Maps/src/MediaWiki/ParserHooks/DisplayMapFunction.php +++ b/www/wiki/extensions/Maps/src/MediaWiki/ParserHooks/DisplayMapFunction.php @@ -3,12 +3,12 @@ namespace Maps\MediaWiki\ParserHooks; use Maps; -use Maps\MapsFunctions; +use Maps\MappingService; use Maps\MappingServices; +use Maps\MapsFactory; use Maps\Presentation\ParameterExtractor; use MWException; -use ParamProcessor; -use ParamProcessor\ProcessedParam; +use ParamProcessor\Processor; use Parser; /** @@ -38,7 +38,7 @@ class DisplayMapFunction { * @throws MWException */ public function getMapHtmlForKeyValueStrings( Parser $parser, array $parameters ): string { - $processor = new \ParamProcessor\Processor( new \ParamProcessor\Options() ); + $processor = new Processor( new \ParamProcessor\Options() ); $service = $this->services->getServiceOrDefault( $this->extractServiceName( @@ -50,14 +50,20 @@ class DisplayMapFunction { $processor->setFunctionParams( $parameters, - array_merge( - self::getHookDefinition( ';' )->getParameters(), - $service->getParameterInfo() - ), - self::getHookDefinition( ';' )->getDefaultParameters() + [], + self::getDefaultParameters() + ); + + $processor->setParameterDefinitions( + $this->getAllParameterDefinitions( $service, ';' ) ); - return $this->getMapHtmlFromProcessor( $parser, $processor ); + $this->trackMap( $parser ); + + return $this->renderer->renderMap( + $service->processingResultToMapParams( $processor->processParameters() ), + $parser + ); } /** @@ -69,65 +75,35 @@ class DisplayMapFunction { * @throws MWException */ public function getMapHtmlForParameterList( Parser $parser, array $parameters ) { - $processor = new \ParamProcessor\Processor( new \ParamProcessor\Options() ); + $processor = new Processor( new \ParamProcessor\Options() ); $service = $this->services->getServiceOrDefault( $this->extractServiceName( $parameters ) ); $this->renderer->service = $service; - $processor->setParameters( - $parameters, - array_merge( - self::getHookDefinition( "\n" )->getParameters(), - $service->getParameterInfo() - ) + $processor->setParameters( $parameters ); + $processor->setParameterDefinitions( + $this->getAllParameterDefinitions( $service, "\n" ) ); - return $this->getMapHtmlFromProcessor( $parser, $processor ); - } - - private function getMapHtmlFromProcessor( Parser $parser, ParamProcessor\Processor $processor ) { - $params = $processor->processParameters()->getParameters(); - - $this->defaultMapZoom( $params ); - $this->trackMap( $parser ); return $this->renderer->renderMap( - $this->processedParametersToKeyValueArray( $params ), + $service->processingResultToMapParams( $processor->processParameters() ), $parser ); } - private function extractServiceName( array $parameters ): string { - $service = ( new ParameterExtractor() )->extract( - [ 'mappingservice', 'service' ], - $parameters - ); - - return $service ?? ''; - } - - private function processedParametersToKeyValueArray( array $params ): array { - $parameters = []; - - foreach ( $params as $parameter ) { - $parameters[$parameter->getName()] = $parameter->getValue(); - } + private function getAllParameterDefinitions( MappingService $service, string $locationDelimiter ) { + $params = []; - return $parameters; - } - - public static function getHookDefinition( string $locationDelimiter ): \ParserHooks\HookDefinition { - return new \ParserHooks\HookDefinition( - [ 'display_map', 'display_point', 'display_points', 'display_line' ], - self::getParameterDefinitions( $locationDelimiter ), - [ 'coordinates' ] - ); - } - - private static function getParameterDefinitions( $locationDelimiter ): array { - $params = MapsFunctions::getCommonParameters(); + $params['mappingservice'] = [ + 'type' => 'string', + 'aliases' => 'service', + 'default' => $GLOBALS['egMapsDefaultService'], + 'values' => MapsFactory::globalInstance()->getMappingServices()->getAllNames(), + 'message' => 'maps-par-mappingservice' + ]; $params['coordinates'] = [ 'type' => 'string', @@ -138,28 +114,25 @@ class DisplayMapFunction { 'message' => 'maps-displaymap-par-coordinates', ]; - return $params; + return MapsFactory::globalInstance()->getParamDefinitionFactory()->newDefinitionsFromArrays( + array_merge( + $params, + $service->getParameterInfo() + ) + ); } - /** - * @param ProcessedParam[] $parameters - */ - private function defaultMapZoom( array &$parameters ) { - if ( array_key_exists( 'zoom', $parameters ) && $parameters['zoom']->wasSetToDefault() && count( - $parameters['coordinates']->getValue() - ) > 1 ) { - $parameters['zoom'] = $this->getParameterWithValue( $parameters['zoom'], false ); - } + private function extractServiceName( array $parameters ): string { + $service = ( new ParameterExtractor() )->extract( + [ 'mappingservice', 'service' ], + $parameters + ); + + return $service ?? ''; } - private function getParameterWithValue( ProcessedParam $param, $value ) { - return new ProcessedParam( - $param->getName(), - $value, - $param->wasSetToDefault(), - $param->getOriginalName(), - $param->getOriginalValue() - ); + public static function getDefaultParameters(): array { + return [ 'coordinates' ]; } private function trackMap( Parser $parser ) { diff --git a/www/wiki/extensions/Maps/src/MediaWiki/ParserHooks/DisplayMapRenderer.php b/www/wiki/extensions/Maps/src/MediaWiki/ParserHooks/DisplayMapRenderer.php index 8c757acd..4fcb93ba 100644 --- a/www/wiki/extensions/Maps/src/MediaWiki/ParserHooks/DisplayMapRenderer.php +++ b/www/wiki/extensions/Maps/src/MediaWiki/ParserHooks/DisplayMapRenderer.php @@ -2,8 +2,6 @@ namespace Maps\MediaWiki\ParserHooks; -use FormatJson; -use Html; use Maps\DataAccess\MediaWikiFileUrlFinder; use Maps\Elements\Location; use Maps\MappingService; @@ -92,7 +90,8 @@ class DisplayMapRenderer { private function handleMarkerData( array &$params ) { $params['centre'] = $this->getCenter( $params['centre'] ); - if ( is_object( $params['wmsoverlay'] ) ) { + // FIXME: this parameter is google maps service specific + if ( array_key_exists( 'wmsoverlay', $params ) && is_object( $params['wmsoverlay'] ) ) { $params['wmsoverlay'] = $params['wmsoverlay']->getJSONObject(); } @@ -122,7 +121,7 @@ class DisplayMapRenderer { private function getLocationJson( array $params ) { $iconUrl = $this->fileUrlFinder->getUrlForFileName( $params['icon'] ); - $visitedIconUrl = $this->fileUrlFinder->getUrlForFileName( $params['visitedicon'] ); + $visitedIconUrl = $this->fileUrlFinder->getUrlForFileName( $params['visitedicon'] ?? '' ); $locationJsonObjects = []; diff --git a/www/wiki/extensions/Maps/src/MediaWiki/ParserHooks/FindDestinationFunction.php b/www/wiki/extensions/Maps/src/MediaWiki/ParserHooks/FindDestinationFunction.php index e7cb319c..05859ca0 100644 --- a/www/wiki/extensions/Maps/src/MediaWiki/ParserHooks/FindDestinationFunction.php +++ b/www/wiki/extensions/Maps/src/MediaWiki/ParserHooks/FindDestinationFunction.php @@ -3,8 +3,8 @@ namespace Maps\MediaWiki\ParserHooks; use DataValues\Geo\Values\LatLongValue; -use Maps\MapsFactory; use Maps\GeoFunctions; +use Maps\MapsFactory; use ParserHook; /** @@ -117,4 +117,4 @@ class FindDestinationFunction extends ParserHook { return [ 'location', 'bearing', 'distance' ]; } -}
\ No newline at end of file +} diff --git a/www/wiki/extensions/Maps/src/MediaWiki/ParserHooks/MapsDocFunction.php b/www/wiki/extensions/Maps/src/MediaWiki/ParserHooks/MapsDocFunction.php index 6a365378..e294736b 100644 --- a/www/wiki/extensions/Maps/src/MediaWiki/ParserHooks/MapsDocFunction.php +++ b/www/wiki/extensions/Maps/src/MediaWiki/ParserHooks/MapsDocFunction.php @@ -2,7 +2,6 @@ namespace Maps\MediaWiki\ParserHooks; -use Maps\MappingServices; use Maps\MapsFactory; use ParamProcessor\ParamDefinition; use ParserHook; @@ -35,12 +34,14 @@ class MapsDocFunction extends ParserHook { public function render( array $parameters ) { $this->language = $parameters['language']; - $params = $this->getServiceParameters( $parameters['service'] ); + $factory = MapsFactory::globalInstance(); - return $this->getParameterTable( $params ); + $params = $this->getServiceParameters( $factory, $parameters['service'] ); + + return $this->getParameterTable( $factory, $params ); } - private function getServiceParameters( $service ) { + private function getServiceParameters( MapsFactory $factory, string $service ) { return array_merge( [ 'zoom' => [ @@ -48,21 +49,17 @@ class MapsDocFunction extends ParserHook { 'message' => 'maps-par-zoom', ] ], - MapsFactory::globalInstance()->getMappingServices()->getService( $service )->getParameterInfo() + $factory->getMappingServices()->getService( $service )->getParameterInfo() ); } /** * Returns the wikitext for a table listing the provided parameters. - * - * @param array $parameters - * - * @return string */ - private function getParameterTable( array $parameters ) { + private function getParameterTable( MapsFactory $factory, array $parameters ): string { $tableRows = []; - $parameters = ParamDefinition::getCleanDefinitions( $parameters ); + $parameters = $factory->getParamDefinitionFactory()->newDefinitionsFromArrays( $parameters ); foreach ( $parameters as $parameter ) { $tableRows[] = $this->getDescriptionRow( $parameter ); diff --git a/www/wiki/extensions/Maps/src/MediaWiki/Specials/SpecialMapEditor.php b/www/wiki/extensions/Maps/src/MediaWiki/Specials/SpecialMapEditor.php index 76b5dad5..0226113e 100644 --- a/www/wiki/extensions/Maps/src/MediaWiki/Specials/SpecialMapEditor.php +++ b/www/wiki/extensions/Maps/src/MediaWiki/Specials/SpecialMapEditor.php @@ -3,7 +3,6 @@ namespace Maps\MediaWiki\Specials; use Maps\GoogleMapsService; -use Maps\MediaWiki\Specials\MapEditorHtml; use SpecialPage; /** @@ -45,7 +44,7 @@ class SpecialMapEditor extends SpecialPage { ) ); - $outputPage->addModules( 'mapeditor' ); + $outputPage->addModules( 'ext.maps.wikitext.editor' ); $editorHtml = new MapEditorHtml( $this->getAttribs() ); $html = $editorHtml->getEditorHtml(); $outputPage->addHTML( $html ); diff --git a/www/wiki/extensions/Maps/src/Presentation/GeoJsonMapPageUi.php b/www/wiki/extensions/Maps/src/Presentation/GeoJsonMapPageUi.php new file mode 100644 index 00000000..89440f1f --- /dev/null +++ b/www/wiki/extensions/Maps/src/Presentation/GeoJsonMapPageUi.php @@ -0,0 +1,83 @@ +<?php + +declare( strict_types = 1 ); + +namespace Maps\Presentation; + +use Html; + +class GeoJsonMapPageUi { + + private $json; + + public static function forExistingPage( string $mapJson ): self { + return new self( $mapJson ); + } + + private function __construct( ?string $json ) { + $this->json = $json; + } + + public function addToOutput( OutputFacade $output ) { + $leafletPath = $GLOBALS['wgScriptPath'] . '/extensions/Maps/resources/lib/leaflet'; + + $output->addHeadItem( + 'MapsGeoJsonHeadItem', + Html::linkedStyle( "$leafletPath/leaflet.css" ) . Html::linkedScript( "$leafletPath/leaflet.js" ) + ); + + $output->addHTML( $this->getJavascript() . $this->getHtml() ); + $output->addModules( 'ext.maps.geojson.page' ); + } + + private function getJavascript(): string { + return Html::element( + 'script', + [], + $this->getJsonJs() + ); + } + + private function getJsonJs(): string { + return 'var GeoJson =' + . $this->json + . ';'; + } + + private function getHtml(): string { + return $this->wrapHtmlInThumbDivs( + Html::rawElement( + 'div', + [ + 'id' => 'GeoJsonMap', + 'style' => 'width: 100%; height: 600px; background-color: #eeeeee; overflow: hidden;', + 'class' => 'maps-map maps-leaflet maps-geojson-editor' + ], + Html::element( + 'div', + [ + 'class' => 'maps-loading-message' + ], + wfMessage( 'maps-loading-map' )->inContentLanguage()->text() + ) + ) + ); + } + + private function wrapHtmlInThumbDivs( string $html ): string { + return Html::rawElement( + 'div', + [ + 'class' => 'thumb' + ], + Html::rawElement( + 'div', + [ + 'class' => 'thumbinner' + ], + $html + ) + ); + } + +} diff --git a/www/wiki/extensions/Maps/src/Presentation/GeoJsonNewPageUi.php b/www/wiki/extensions/Maps/src/Presentation/GeoJsonNewPageUi.php new file mode 100644 index 00000000..5de1df71 --- /dev/null +++ b/www/wiki/extensions/Maps/src/Presentation/GeoJsonNewPageUi.php @@ -0,0 +1,27 @@ +<?php + +namespace Maps\Presentation; + +class GeoJsonNewPageUi { + + private $output; + + public function __construct( OutputFacade $output ) { + $this->output = $output; + } + + public function addToOutput() { + $this->output->addModules( 'ext.maps.geojson.new.page' ); + + $this->output->addHtml( + \Html::element( + 'button', + [ + 'id' => 'maps-geojson-new' + ], + wfMessage( 'maps-geo-json-create-page-button' )->inContentLanguage()->text() + ) + ); + } + +} diff --git a/www/wiki/extensions/Maps/src/Presentation/MapHtmlBuilder.php b/www/wiki/extensions/Maps/src/Presentation/MapHtmlBuilder.php index aa47e558..7d74ad34 100644 --- a/www/wiki/extensions/Maps/src/Presentation/MapHtmlBuilder.php +++ b/www/wiki/extensions/Maps/src/Presentation/MapHtmlBuilder.php @@ -22,12 +22,18 @@ class MapHtmlBuilder { 'div', [ 'id' => $mapName, - 'style' => "width: {$params['width']}; height: {$params['height']}; background-color: #cccccc; overflow: hidden;", + 'style' => "width: {$params['width']}; height: {$params['height']}; background-color: #eeeeee; overflow: hidden;", 'class' => 'maps-map maps-' . $serviceName ], - wfMessage( 'maps-loading-map' )->inContentLanguage()->escaped() . Html::element( 'div', + [ + 'class' => 'maps-loading-message' + ], + wfMessage( 'maps-loading-map' )->inContentLanguage()->text() + ) + . Html::element( + 'div', [ 'style' => 'display:none', 'class' => 'mapdata' ], FormatJson::encode( $params ) ) diff --git a/www/wiki/extensions/Maps/src/Presentation/MapsDistanceParser.php b/www/wiki/extensions/Maps/src/Presentation/MapsDistanceParser.php index c8fb0ef1..7c0d595a 100644 --- a/www/wiki/extensions/Maps/src/Presentation/MapsDistanceParser.php +++ b/www/wiki/extensions/Maps/src/Presentation/MapsDistanceParser.php @@ -99,7 +99,7 @@ class MapsDistanceParser { $strlen = strlen( $distance ); for ( $i = 0; $i < $strlen; $i++ ) { - if ( !ctype_digit( $distance{$i} ) && !in_array( $distance{$i}, [ ',', '.' ] ) ) { + if ( !ctype_digit( $distance[$i] ) && !in_array( $distance[$i], [ ',', '.' ] ) ) { $value = substr( $distance, 0, $i ); $unit = substr( $distance, $i ); break; diff --git a/www/wiki/extensions/Maps/src/Presentation/OutputFacade.php b/www/wiki/extensions/Maps/src/Presentation/OutputFacade.php new file mode 100644 index 00000000..119f3b1d --- /dev/null +++ b/www/wiki/extensions/Maps/src/Presentation/OutputFacade.php @@ -0,0 +1,62 @@ +<?php + +namespace Maps\Presentation; + +use OutputPage; +use ParserOutput; + +class OutputFacade { + + /** + * @var OutputPage + */ + private $outputPage; + + /** + * @var ParserOutput + */ + private $parserOutput; + + public static function newFromOutputPage( OutputPage $outputPage ) { + $instance = new self(); + $instance->outputPage = $outputPage; + return $instance; + } + + public static function newFromParserOutput( ParserOutput $parserOutput ) { + $instance = new self(); + $instance->parserOutput = $parserOutput; + return $instance; + } + + public function addHtml( string $html ) { + if ( $this->outputPage !== null ) { + $this->outputPage->addHTML( $html ); + } + + if ( $this->parserOutput !== null ) { + $this->parserOutput->setText( $this->parserOutput->getRawText() . $html ); + } + } + + public function addModules( string ...$modules ) { + if ( $this->outputPage !== null ) { + $this->outputPage->addModules( $modules ); + } + + if ( $this->parserOutput !== null ) { + $this->parserOutput->addModules( $modules ); + } + } + + public function addHeadItem( string $name, string $html ) { + if ( $this->outputPage !== null ) { + $this->outputPage->addHeadItem( $name, $html ); + } + + if ( $this->parserOutput !== null ) { + $this->parserOutput->addHeadItem( $html, $name ); + } + } + +} diff --git a/www/wiki/extensions/Maps/src/SemanticMW/ResultPrinters/MapPrinter.php b/www/wiki/extensions/Maps/src/SemanticMW/ResultPrinters/MapPrinter.php index 6ab945f6..7a5f64b5 100644 --- a/www/wiki/extensions/Maps/src/SemanticMW/ResultPrinters/MapPrinter.php +++ b/www/wiki/extensions/Maps/src/SemanticMW/ResultPrinters/MapPrinter.php @@ -2,19 +2,15 @@ namespace Maps\SemanticMW\ResultPrinters; -use FormatJson; -use Html; use Linker; use Maps\Elements\BaseElement; use Maps\Elements\Location; use Maps\FileUrlFinder; use Maps\MappingService; -use Maps\MapsFunctions; use Maps\Presentation\ElementJsonSerializer; use Maps\Presentation\MapHtmlBuilder; use Maps\Presentation\WikitextParser; use Maps\Presentation\WikitextParsers\LocationParser; -use ParamProcessor\ParamDefinition; use Parser; use SMW\Query\ResultPrinters\ResultPrinter; use SMWOutputs; @@ -113,6 +109,8 @@ class MapPrinter extends ResultPrinter { return $this->fatalErrorMsg; } + $this->isHTML = true; + $factory = \Maps\MapsFactory::newDefault(); $this->locationParser = $factory->newLocationParser(); $this->fileUrlFinder = $factory->getFileUrlFinder(); @@ -205,7 +203,7 @@ class MapPrinter extends ResultPrinter { $params['centre'] = $this->getCenter( $params['centre'] ); $iconUrl = $this->fileUrlFinder->getUrlForFileName( $params['icon'] ); - $visitedIconUrl = $this->fileUrlFinder->getUrlForFileName( $params['visitedicon'] ); + $visitedIconUrl = $this->fileUrlFinder->getUrlForFileName( $params['visitedicon'] ?? '' ); $params['locations'] = $this->getJsonForStaticLocations( $params['staticlocations'], @@ -318,10 +316,6 @@ class MapPrinter extends ResultPrinter { $params = parent::getParameters(); $paramInfo = $this->getParameterInfo(); - // Do not display this as an option, as the format already determines it - // TODO: this can probably be done cleaner with some changes in Maps - unset( $paramInfo['mappingservice'] ); - $params = array_merge( $params, $paramInfo ); return $params; @@ -335,10 +329,7 @@ class MapPrinter extends ResultPrinter { private function getParameterInfo() { global $smgQPShowTitle, $smgQPTemplate, $smgQPHideNamespace; - $params = array_merge( - ParamDefinition::getCleanDefinitions( MapsFunctions::getCommonParameters() ), - $this->service->getParameterInfo() - ); + $params = $this->service->getParameterInfo(); $params['staticlocations'] = [ 'type' => 'mapslocation', |