We want to have more efficient map views for readers by immediately querying the external data (geopoints, geoshapes, etc.) into the extension ParserCache data when editing is done.
## Requirements
* [x] Implement in Kartographer, behind a feature flag in parallel with the existing behavior.
* POC is done in SimpleStyleParser.php but this normalization function should be moved out of this class anyway.
* Should be performed before simplestyle transforms, for the Commons "Data" .map path.
[] Set "expensive" parser flag.
* Inlined geoshape will go directly into the parser cache along with other geometry, probably no changes needed there.
[x] Put it behind a feature flag, old code should still be run by default.
[x] Failed requests can fall back to the old behavior gracefully after logging a warning.
* [ ] MediaWiki must be able to route requests to kartotherian directly.
* Development environment requires some tweaks to docker-compose.yml to allow local MediaWiki to contact local kartotherian.
* Production might not allow this until we set it up explicitly.
* [ ] Must work for ids and SPARQL query, for geoshape, geoline, geopoint.
* [ ] Copy behaviour for geomaskEach service is handled slightly differently by the external data parser, see mapdata for the reference implementations that we must match, https://gerrit.wikimedia.org/g/mapdata/+/refs/changes/66/858566/26/src/ExternalDataParser.js#40 . The distinct handling for each group:
* [ ] Handle service page * "page" or [[ https://www.mediawiki.org/wiki/Help:Extension:Kartographer#Map_data_from_Commons | maps from commons ]] are passed through directly, by a non-recursive "extend" or "array_merge" at the GeoJSON object level.
* [ ] Must work for [[ https://www.mediawiki.org/wiki/Help:Extension:Kartographer#Map_data_from_Commons | maps from commons ]] * geoshape, geoline, and geopoint have the same top-level merge, and also any default "properties" along with the original external mapdata link are merged under the properties of each Feature in the expanded "features" of a FeatureCollection, if any.
* [x] Keep kartotherian code for expanding geoshapes--although this can go away in the long term * [ ] geomask calculates the reverse of a polygon. TODO: It looks like default simplestyle properties are not copied into features for geomask. Document this on the help page and as a follow-up task in Phabricator.
[x] Handle external data and default properties similar to existing approach* [x] Don't damage karotherian code for expanding geoshapes, this is needed for our migration fallback strategy. In the long term, this will happily go away.
[x] Must work for mapdata which is a list of GeoJSON objects
* This is already being supported by the calling code, and our ExternalDataLoader is called with singular elementsExternalDataLoader's "parse" entrypoint iterates over its array argument and calls "extend" for each singular geojson. I'm not sure where a single geojson is coerced to be an array.
## Open questions
* What should we do when the expensive flag signals too expensive?
* There seems to be a difference in the results for the current approach and this one. Looks like not all data points are found currently. Why?
* Should we fall back to the old behaviour if it is faulty?
* Should we exclude the "page" service [[ https://gerrit.wikimedia.org/r/c/mediawiki/extensions/Kartographer/+/855984/comments/9d3100b5_cee78977 | for now ]]?
## For review
Enable feature flag `KartographerExternalDataParseTimeFetch` in extension.json.
Change kartotherian server url in local settings:
```
$wgKartographerMapServer = "https://maps.wikimedia.org";
```
Example that has default properties and properties in external data:
```
<mapframe text="Geopoints via sparql" width="300" height="300" zoom="13" align="left" latitude="43.735011" longitude="7.413197">
{
"type": "ExternalData",
"service": "geopoint",
"query": "SELECT DISTINCT ?id ?geo (IF(?type = wd:Q33506, 'museum', '') AS ?marker_symbol) WHERE { ?id wdt:P17 wd:Q235; wdt:P31 ?type; wdt:P625 ?geo.} LIMIT 50",
"properties": {
"marker-size": "large",
"marker-symbol": "circle",
"marker-color": "#FF5733",
}
}
</mapframe>
```