Yurik has uploaded a new change for review. https://gerrit.wikimedia.org/r/311316
Change subject: Implement API to get the list of external map links ...................................................................... Implement API to get the list of external map links The api is: /w/api.php?action=mapdata&format=json&formatversion=2 For now, something to get us started: * external links are stored in a file externalLinks.json * File must have the following structure: { "services": [ { "name": "OpenStreetMap", // name of the service, or localized object {"languagecode":"value", ...} "links": [ { "type": "map", // can also be: satellite, terrain, other "url": "http://...", // this value may include values like {latdegdec}, {londegdec}, etc "label": { // optional - either a string or a localized object "en": "english name", "fr": "french name" } }, ... Bug: T145667 Change-Id: I99e7d67c9296fe2e1a48a644e60de1ae550f3e59 --- M extension.json A externalLinks.json M i18n/en.json M i18n/qqq.json A includes/ApiMapData.php 5 files changed, 583 insertions(+), 1 deletion(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Kartographer refs/changes/16/311316/1 diff --git a/extension.json b/extension.json index a56ab62..c834317 100644 --- a/extension.json +++ b/extension.json @@ -23,6 +23,7 @@ "Map": "Kartographer\\SpecialMap" }, "AutoloadClasses": { + "Kartographer\\ApiMapData": "includes/ApiMapData.php", "Kartographer\\ApiQueryMapData": "includes/ApiQueryMapData.php", "Kartographer\\ApiSanitizeMapData": "includes/ApiSanitizeMapData.php", "Kartographer\\CoordFormatter": "includes/CoordFormatter.php", @@ -39,7 +40,8 @@ "Kartographer\\Projection\\Transformation": "includes/Projection/Transformation.php" }, "APIModules": { - "sanitize-mapdata": "Kartographer\\ApiSanitizeMapData" + "sanitize-mapdata": "Kartographer\\ApiSanitizeMapData", + "mapdata": "Kartographer\\ApiMapData" }, "APIPropModules": { "mapdata": "Kartographer\\ApiQueryMapData" diff --git a/externalLinks.json b/externalLinks.json new file mode 100644 index 0000000..ecb5d71 --- /dev/null +++ b/externalLinks.json @@ -0,0 +1,422 @@ +{ + "services": [ + { + "name": "ACME Mapper", + "links": [ + { + "type": "map", + "url": "http://mapper.acme.com/?ll={latdegdec},{londegdec}&z={osmzoom}&t=M&marker0={latdegdec},{londegdec},{titlee}" + }, + { + "type": "satellite", + "url": "http://mapper.acme.com/?ll={latdegdec},{londegdec}&z={osmzoom}&t=H&marker0={latdegdec},{londegdec},{titlee}" + }, + { + "type": "terrain", + "url": "http://mapper.acme.com/?ll={latdegdec},{londegdec}&z={osmzoom}&t=R&marker0={latdegdec},{londegdec},{titlee}" + }, + { + "type": "other", + "label": { + "en": "topo" + }, + "url": "http://mapper.acme.com/?ll={latdegdec},{londegdec}&z={osmzoom}&t=T&marker0={latdegdec},{londegdec},{titlee}" + }, + { + "type": "other", + "label": { + "en": "Mapnik" + }, + "url": "http://mapper.acme.com/?ll={latdegdec},{londegdec}&z={osmzoom}&t=K&marker0={latdegdec},{londegdec},{titlee}" + } + ] + }, + { + "name": "Apple Maps", + "links": [ + { + "type": "map", + "url": "https://maps.apple.com/?q={latdegdec},{londegdec}" + }, + { + "type": "satellite", + "url": "https://maps.apple.com/?q={latdegdec},{londegdec}&t=k" + } + ] + }, + { + "name": "Arctic.io", + "links": [ + { + "type": "other", + "label": { + "en": "Daily Satellite" + }, + "url": "http://www.arctic.io/wikipedia/?lon={londegdec}&lat={latdegdec}&title={titlee}" + } + ] + }, + { + "name": "Bing Maps", + "featured": true, + "links": [ + { + "type": "map", + "url": "https://www.bing.com/maps/?v=2&cp={latdegdec}~{londegdec}&style=r&lvl={osmzoom}&sp=Point.{latdegdec}_{londegdec}_{titlee}___" + }, + { + "type": "other", + "label": { + "en": "Aerial" + }, + "url": "https://www.bing.com/maps/?v=2&cp={latdegdec}~{londegdec}&style=h&lvl={osmzoom}&sp=Point.{latdegdec}_{londegdec}_{titlee}___" + }, + { + "type": "other", + "label": { + "en": "Bird's Eye" + }, + "url": "https://www.bing.com/maps/?v=2&cp={latdegdec}~{londegdec}&style=o&lvl={osmzoom}&sp=Point.{latdegdec}_{londegdec}_{titlee}___" + } + ] + }, + { + "name": "Blue Marble Navigator", + "links": [ + { + "type": "satellite", + "url": "http://www.blue-marble.de?lon={londegdec}&nlat={latdegdec}&borders&geonames&townnames&zoom&overlay=14&base=7" + }, + { + "type": "other", + "label": { + "en": "Night Lights" + }, + "url": "http://www.blue-marble.de/nightlights?ll={latdegdec},{londegdec}" + } + ] + }, + { + "name": "Flash Earth", + "links": [ + { + "type": "satellite", + "url": "http://www.flashearth.com/?lat={latdegdec}&lon={londegdec}&z=15&r=0&src=ggl" + } + ] + }, + { + "name": "GeaBios", + "links": [ + { + "type": "satellite", + "url": "http://www.geabios.com/html/services/maps/PublicMap.htm?lat={latdegdec}&lon={londegdec}&fov={span}&title={titlee}" + } + ] + }, + { + "name": "GeoNames", + "links": [ + { + "type": "satellite", + "url": "http://www.geonames.org/maps/google_{latdegdec}_{londegdec}.html" + }, + { + "type": "other", + "label": { + "en": "Text (XML)" + }, + "url": "http://ws.geonames.org/extendedFindNearby?lat={latdegdec}&lng={londegdec}" + } + ] + }, + { + "name": "Google Earth", + "links": [ + { + "type": "other", + "label": { + "en": "Open" + }, + "url": "https://toolserver.org/~kolossos/earth.php?long={londegdec}&lat={latdegdec}&name={pagenamee}" + }, + { + "type": "other", + "label": { + "en": "w/ meta data" + }, + "url": "https://tools.wmflabs.org/geocommons/earth.kml?latdegdec={latdegdec}&londegdec={londegdec}&scale={scale}&title={titlee}" + } + ] + }, + { + "name": "Google Maps", + "featured": true, + "links": [ + { + "type": "map", + "url": "https://maps.google.com/maps?ll={latdegdec},{londegdec}&q={latdegdec},{londegdec}&hl={language}&t=m&z={osmzoom}" + }, + { + "type": "satellite", + "url": "https://maps.google.com/maps?ll={latdegdec},{londegdec}&q={latdegdec},{londegdec}&hl={language}&t=h&z={osmzoom}" + }, + { + "type": "terrain", + "url": "https://www.google.com/maps/place//@{latdegdec},{londegdec},{osmzoom}z/data=!4m2!3m1!1s0x0:0x0!5m1!1e4?hl=en" + } + ] + }, + { + "name": "GPS Visualizer", + "links": [ + { + "type": "map", + "url": "http://www.gpsvisualizer.com/map_input?special=wikipedia&format=google&bg_map=google_map&sp_width=50km&google_zoom_level={zoom}&google_wpt_labels=1&form:data=name,latitude,longitude%0D%22{titlee}%22,{latdegdec},{londegdec}" + }, + { + "type": "satellite", + "url": "http://www.gpsvisualizer.com/map_input?special=wikipedia&format=google&bg_map=google_hybrid&sp_width=50km&google_zoom_level={zoom}&google_wpt_labels=1&form:data=name,latitude,longitude%0D%22{titlee}%22,{latdegdec},{londegdec}" + }, + { + "type": "other", + "label": { + "en": "topo" + }, + "url": "http://www.gpsvisualizer.com/map_input?special=wikipedia&format=google&bg_map=google_arcgistopo_world&sp_width=50km&google_zoom_level={zoom}&google_wpt_labels=1&form:data=name,latitude,longitude%0D%22{titlee}%22,{latdegdec},{londegdec}" + }, + { + "type": "other", + "label": { + "en": "Drawing utility" + }, + "url": "http://www.gpsvisualizer.com/draw/?zoom={zoom}¢er={latdegdec},{londegdec}&marker={titlee}" + } + ] + }, + { + "name": "HERE", + "links": [ + { + "type": "map", + "url": "https://www.here.com/location/?map={latdegdec},{londegdec},{osmzoom},normal&msg={titlee}" + }, + { + "type": "satellite", + "url": "https://www.here.com/location/?map={latdegdec},{londegdec},{osmzoom},satellite&msg={titlee}" + }, + { + "type": "terrain", + "url": "https://www.here.com/location/?map={latdegdec},{londegdec},{osmzoom},terrain&msg={titlee}" + } + ] + }, + { + "name": "MapQuest", + "links": [ + { + "type": "map", + "url": "http://www.mapquest.com/?center={latdegdec},{londegdec}&zoom={osmzoom}&q={titlee}" + } + ] + }, + { + "name": "MapTech", + "links": [ + { + "type": "map", + "url": "http://mapserver.maptech.com/homepage/index.cfm?lat={latdegdec}&lon={londegdec}&scale=24000&zoom=50&type=1" + } + ] + }, + { + "name": "NASA World Wind", + "links": [ + { + "type": "other", + "label": { + "en": "Open" + }, + "url": "worldwind://goto/world=Earth&lat={latdegdec}&lon={londegdec}&view={span}" + } + ] + }, + { + "name": "Norkart Virtual Globe", + "links": [ + { + "type": "satellite", + "url": "http://www.virtual-globe.info/VirtualGlobeStarter.php?request=page&dataset=http://www.virtual-globe.info/globe.vgml&lookat={londegdec},{latdegdec},{scale}" + } + ] + }, + { + "name": "Open Street Map", + "featured": true, + "links": [ + { + "type": "map", + "url": "https://www.openstreetmap.org/?mlat={latdegdec}&mlon={londegdec}&zoom={osmzoom}&layers=M" + }, + { + "type": "other", + "label": { + "en": "more maps" + }, + "url": "https://tools.wmflabs.org/geohack/geohack.php?project=osm&pagename={pagenamee}&language=en¶ms={params}&title={titlee}" + }, + { + "type": "other", + "label": { + "en": "Nominatim (reverse geocoding)" + }, + "url": "http://nominatim.openstreetmap.org/reverse?lat={latdegdec}&lon={londegdec}&zoom={zoom}" + } + ] + }, + { + "name": "Shaded Relief", + "links": [ + { + "type": "terrain", + "url": "http://www.shaded-relief.com/?gt={latdegdec}&gl={londegdec}&z=9&t=4" + } + ] + }, + { + "name": "SkyVector", + "links": [ + { + "type": "other", + "label": { + "en": "Aeronautical chart" + }, + "url": "https://skyvector.com/?ll={latdegdec},{londegdec}&zoom=2" + } + ] + }, + { + "name": "TerraServer", + "links": [ + { + "type": "satellite", + "url": "https://www.terraserver.com/view?utf8=%E2%9C%93&search_text=&searchLat=&searchLng=&lat={latdegdec}&lng={londegdec}&bbox=¢er=" + } + ] + }, + { + "name": "Topomapper", + "links": [ + { + "type": "other", + "label": { + "en": "topo" + }, + "url": "http://www.topomapper.com/index.html?zoom={osmzoom}&lat={latdegdec}&lon={londegdec}" + }, + { + "type": "other", + "label": { + "en": "Dual view" + }, + "url": "http://www.topomapper.com/splitscreen.html?zoom={osmzoom}&lat={latdegdec}&lon={londegdec}&layers=00000000B0" + } + ] + }, + { + "name": "Vpike.com", + "links": [ + { + "type": "other", + "label": { + "en": "Vpike.com" + }, + "url": "http://www.vpike.com?e={latdegdec},{londegdec}:168.5994445130002::sv:0" + } + ] + }, + { + "name": "Waze", + "links": [ + { + "type": "map", + "url": "https://www.waze.com/livemap/?zoom={osmzoom}&lat={latdegdec}&lon={londegdec}" + }, + { + "type": "other", + "label": { + "en": "Editor" + }, + "url": "https://www.waze.com/editor/?lon={londegdec}&lat={latdegdec}" + }, + { + "type": "other", + "label": { + "en": "open in app" + }, + "url": "http://waze.to/?ll={latdegdec},{londegdec}" + }, + { + "type": "other", + "label": { + "en": "navigate in app" + }, + "url": "http://waze.to/?ll={latdegdec},{londegdec}&navigate=yes" + } + ] + }, + { + "name": "Wikimapia", + "featured": true, + "links": [ + { + "type": "map", + "url": "http://wikimapia.org/#lang={language}&lat={latdegdec}&lon={londegdec}&z={osmzoom}&m=w" + }, + { + "type": "map", + "mobile": true, + "url": "http://wikimapia.org/m/#lang={language}&lat={latdegdec}&lon={londegdec}&z={osmzoom}&m=w" + }, + { + "type": "satellite", + "url": "http://wikimapia.org/#lang={language}&lat={latdegdec}&lon={londegdec}&z={osmzoom}&m=b" + }, + { + "type": "satellite", + "mobile": true, + "url": "http://wikimapia.org/m/#lang={language}&lat={latdegdec}&lon={londegdec}&z={osmzoom}&m=b" + }, + { + "type": "other", + "label": { + "en": "+ old places" + }, + "url": "http://wikimapia.org/#lang={language}&lat={latdegdec}&lon={londegdec}&z={osmzoom}&m=b&v=8" + } + ] + }, + { + "name": "WikiMiniAtlas", + "links": [ + { + "type": "map", + "url": "https://wma.wmflabs.org/iframe.html?wma={latdegdec}_{londegdec}_700_500_{language}_{zoom}_en&globe=Earth&lang={language}&page={pagenamee}" + } + ] + }, + { + "name": "Yandex.Maps", + "links": [ + { + "type": "map", + "url": "https://maps.yandex.com/?ll={londegdec},{latdegdec}&spn={span},{span}&l=map&pt={londegdec},{latdegdec}" + }, + { + "type": "satellite", + "url": "https://maps.yandex.com/?ll={londegdec},{latdegdec}&spn={span},{span}&l=sat&pt={londegdec},{latdegdec}" + } + ] + } + ] +} diff --git a/i18n/en.json b/i18n/en.json index 6d05cf2..e089c0e 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -4,6 +4,8 @@ "Yuri Astrakhan" ] }, + "apihelp-mapdata-description": "Get configuration for Kartographer extension", + "apihelp-mapdata-example": "Get external map links configuration", "apihelp-sanitize-mapdata-description": "Performs data validation for Kartographer extension", "apihelp-sanitize-mapdata-param-title": "Title of page on which this GeoJSON is supposed to be located. If no title is provided, a dummy one will be used.", "apihelp-sanitize-mapdata-param-text": "GeoJSON to sanitize", @@ -36,6 +38,10 @@ "kartographer-specialmap-invalid-coordinates": "Invalid coordinates supplied", "kartographer.css": "/* CSS placed here will be applied to all pages with maps */", "kartographer.js": "/* Any JavaScript here will be loaded for all users on load of the map-containing pages */", + "kartographer-mapinfo-map": "Map", + "kartographer-mapinfo-satellite": "Satellite", + "kartographer-mapinfo-terrain": "Terrain", + "kartographer-mapinfo-other": "Other", "leafletdraw-draw-handlers-circle-radius": "Radius", "leafletdraw-draw-handlers-circle-tooltip-start": "Click and drag to draw a circle", "leafletdraw-draw-handlers-marker-tooltip-start": "Click map to place a marker", diff --git a/i18n/qqq.json b/i18n/qqq.json index 6fb1565..bfaca5e 100644 --- a/i18n/qqq.json +++ b/i18n/qqq.json @@ -7,6 +7,8 @@ "Amire80" ] }, + "apihelp-mapdata-description": "{{doc-apihelp-description|mapdata}}", + "apihelp-mapdata-example": "{{doc-apihelp-example|mapdata}}", "apihelp-sanitize-mapdata-description": "{{doc-apihelp-description|sanitize-mapdata}}", "apihelp-sanitize-mapdata-param-title": "{{doc-apihelp-param|sanitize-mapdata|title}}", "apihelp-sanitize-mapdata-param-text": "{{doc-apihelp-param|sanitize-mapdata|text}}", @@ -39,6 +41,10 @@ "kartographer-specialmap-invalid-coordinates": "Displayed by Special:Map when no valid coordinates are supplied", "kartographer.css": "{{optional}}", "kartographer.js": "{{optional}}", + "kartographer-mapinfo-map": "Full screen map info sidebar - type of external link - map", + "kartographer-mapinfo-satellite": "Full screen map info sidebar - type of external link - satellite", + "kartographer-mapinfo-terrain": "Full screen map info sidebar - type of external link - terrain", + "kartographer-mapinfo-other": "Full screen map info sidebar - type of external link - other", "leafletdraw-draw-handlers-circle-radius": "Label for circle radius\n{{Identical|Radius}}", "leafletdraw-draw-handlers-circle-tooltip-start": "Tooltip for how to start drawing a circle", "leafletdraw-draw-handlers-marker-tooltip-start": "Tooltip for how to place a marker", diff --git a/includes/ApiMapData.php b/includes/ApiMapData.php new file mode 100644 index 0000000..0f19b55 --- /dev/null +++ b/includes/ApiMapData.php @@ -0,0 +1,146 @@ +<?php +/** + * + * @license MIT + * @file + * + * @author Yuri Astrakhan + */ + +namespace Kartographer; + +use ApiBase; +use FormatJson; +use Language; +use Parser; +use ParserOptions; +use stdClass; +use Title; + +/** + * This class implements action=mapdata API, getting mapdata settings + * @package Kartographer + */ +class ApiMapData extends ApiBase { + + public function execute() { + /** @var Parser $wgParser */ + global $wgParser; + + $language = $this->getLanguage(); + + $title = Title::makeTitle( NS_MAIN, 'Kartographer' ); + $parser = $wgParser->getFreshParser(); + $parserOptions = new ParserOptions( $this->getUser(), $language ); + $parser->startExternalParse( $title, $parserOptions, Parser::OT_HTML ); + $parser->setTitle( $title ); + $parser->clearState(); + + $st = FormatJson::parse( + file_get_contents( __DIR__ . '/../externalLinks.json' ), + FormatJson::TRY_FIXING | FormatJson::STRIP_COMMENTS + ); + + if ( !$st->isOK() ) { + list( , $msg ) = $this->getErrorFromStatus( $st ); + ApiBase::dieDebug( __METHOD__, 'Unable to parse externalLinks.json: ' . $msg ); + } + + $data = $st->getValue(); + + foreach ( $data->services as &$service ) { + $service->name = self::parseString( $service->name, $parser, $language ); + + foreach ( $service->links as &$link ) { + if ( property_exists( $link, 'label' ) ) { + $val = $link->label; + } else { + switch ( $link->type ) { + case 'map': + $val = wfMessage( 'kartographer-mapinfo-map' )->plain(); + break; + case 'satellite': + $val = wfMessage( 'kartographer-mapinfo-satellite' )->plain(); + break; + case 'terrain': + $val = wfMessage( 'kartographer-mapinfo-terrain' )->plain(); + break; + case 'other': + $val = wfMessage( 'kartographer-mapinfo-other' )->plain(); + break; + default: + $val = $link->type; + } + } + $link->label = self::parseString( $val, $parser, $language ); + } + } + + $this->getResult() + ->addValue( null, + $this->getModuleName(), + $data + ); + } + + /** + * @param string|object $value + * @param Parser $parser + * @param Language|\StubUserLang $language language object + * @return string + */ + private static function parseString( $value, $parser, $language ) { + if ( is_object( $value ) ) { + $value = self::pickLocalizedString( $value, $language ); + } + return trim( Parser::stripOuterParagraph( $parser->recursiveTagParseFully( $value ) ) ); + } + + /** + * Duplicate from JsonConfig ext - JCUtils::pickLocalizedString + * TODO: Move this code to core + * + * Find a message in a dictionary for the given language, + * or use language fallbacks if message is not defined. + * @param stdClass $map Dictionary of languageCode => string + * @param Language|\StubUserLang $lang language object + * @return string message from the dictionary or "" if nothing found + */ + public static function pickLocalizedString( stdClass $map, $lang ) { + $langCode = $lang->getCode(); + if ( property_exists( $map, $langCode ) ) { + return $map->$langCode; + } + foreach ( $lang->getFallbackLanguages() as $l ) { + if ( property_exists( $map, $l ) ) { + return $map->$l; + } + } + // If fallbacks fail, check if english is defined + if ( property_exists( $map, 'en' ) ) { + return $map->en; + } + // Return first available value, or an empty string + // There might be a better way to get the first value from an object + $map = (array)$map; + return reset( $map ) ? : ''; + } + + public function getAllowedParams() { + return []; + } + + protected function getExamplesMessages() { + return [ + 'action=mapdata' => 'apihelp-mapdata-example', + ]; + } + + /** + * Indicate that this API can change at any time + * @return bool + */ + public function isInternal() { + return true; + } +} -- To view, visit https://gerrit.wikimedia.org/r/311316 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I99e7d67c9296fe2e1a48a644e60de1ae550f3e59 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/Kartographer Gerrit-Branch: master Gerrit-Owner: Yurik <yu...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits