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
* [ ] Each 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:
* [ ] "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.
* [x] 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.
* [ ] 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] 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
* ExternalDataLoader'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?
* Should we fall back to the old behaviour if it is faulty?
## 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>
```