You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Expand the MediaWiki:Maps config page beyond Leaflet layers (#927)
* Expand the MediaWiki:Maps config page beyond Leaflet layers
Fixes#926
Follows-up to #925
Generalizes the MediaWiki:Maps config page (added in #925 for Leaflet layers) to expose
most Maps settings, driven by a single declarative schema so that exposing a setting is one
schema entry rather than bespoke code.
## Design
Maps\Config\ConfigSchema lists every exposed setting as a ConfigSetting: page group + key,
the egMaps*/smgQP* setting it overrides, its value type, and its merge strategy. It drives
both save-time validation and read-time application:
* ConfigValidator walks the schema on save (EditFilter hook), rejecting unknown groups/keys
and per-value type errors.
* EffectiveSettings is the one effective-settings lookup wrapping the PHP settings with the
schema-translated wiki overlay. It reads the page lazily at parse time, memoizes the
result, falls back to the PHP settings on any Throwable or when disabled, and ignores wiki
values that fail their type validation. All exposed-setting consumption sites read through
it instead of $GLOBALS.
Value types are small reusable objects: boolean, integer, string, enum, enum list, string
list, dimension, positive-number map, pattern, plus the layer-definitions and availability
specials. Wiki values replace the PHP value, except layerDefinitions, availableLayers and
availableOverlays, which merge per name via a MergeStrategy attribute of those entries.
The #925 Leaflet-specific classes were reshaped into this general concept:
LeafletConfigValidator -> ConfigValidator, WikiLeafletConfigSource -> WikiPageConfigSource
(now reads the whole page), CombiningLeafletConfigLookup -> EffectiveSettings;
LeafletConfig/LeafletConfigLookup dissolved into LeafletService reading the effective
settings directly. LeafletLayerContract and AttributionSanitizer are unchanged.
## Exposed and excluded
Groups: general, coordinates, geocoding, semanticMediaWiki, leaflet, googleMaps (see the
README for the full key list). Secrets/API keys, script-injection primitives, the caches and
setup-time switches stay PHP-only, as decided in the issue.
Two settings from the issue's list are deviated from:
* defaultService is excluded. egMapsDefaultService is consumed when MappingServices is
constructed and when SMW result-format aliases are registered, both during extension setup
before the config page can be read. Routing it would force a wiki read at setup, defeating
the lazy design, so it stays PHP-only.
* internationalDirectionLabels is excluded. egMapsInternatDirectionLabels is not read
anywhere in the code, so exposing it would have no effect.
distanceUnit is validated as a plain string rather than against the effective units: an
unknown default unit self-heals to the first available unit at runtime and cannot hard-fail.
## Security
mapWidth/mapHeight use a strict dimension pattern (they reach inline styles),
googleMaps.language a strict pattern (it reaches the Google API URL), and distance unit names
are restricted to alphanumerics (they reach a regex and rendered output). Layer definitions
keep the #925 hardening unchanged.
## Tests
Table-driven unit tests per value type, schema and validator tests, EffectiveSettings merge,
fallback and memoization tests, and integration spot checks that a wiki-set value lands end
to end. All #925 tests are preserved through the renames.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Reject a trailing newline in the config value patterns
The dimension, distance-unit-name and Google Maps language patterns anchored
with $, which matches just before a trailing newline. Add the D modifier so a
value with a trailing newline is rejected, keeping these strict patterns fully
strict before their style, URL and regex sinks. Harmless in practice since the
sinks escape or encode, found in review.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Correct README wording about config page key naming
Several page keys are deliberately renamed from their PHP settings
(e.g. pagesWithMapsCategory for egMapsEnableCategory), so the reference
list should not claim the names are the same.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: RELEASE-NOTES.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,7 +7,7 @@ different releases and which versions of PHP and MediaWiki they support, see the
7
7
8
8
Released on TBD.
9
9
10
-
* Added an on-wiki JSON configuration page at `MediaWiki:Maps`for the Leaflet layer settings (custom layer definitions, the default and available base layers and overlays). It is editable only by administrators and interface administrators, is validated on save, and is combined with `LocalSettings.php` with the wiki page taking precedence. Set `$egMapsEnableInWikiConfig` to `false` to disable it.
10
+
* Added an on-wiki JSON configuration page at `MediaWiki:Maps`exposing most Maps settings, grouped by service and topic (general map, coordinate, geocoding, Semantic MediaWiki, Leaflet and Google Maps options), including the Leaflet custom layer definitions and available layers. It is editable only by administrators and interface administrators, is validated on save, and is combined with `LocalSettings.php` with the wiki page taking precedence. Secrets, script-injection primitives and setup-time settings stay exclusive to `LocalSettings.php`. Set `$egMapsEnableInWikiConfig` to `false` to disable it.
11
11
* Hardened the custom Leaflet layer definitions used by `$egMapsLeafletLayerDefinitions` and the config page (breaking change): the `url` and `errorTileUrl` must be `http(s)` URLs, only an allowlist of Leaflet `options` is kept, and `attribution` is sanitized to plain text and `http(s)` links. Definitions relying on raw HTML attribution or non-allowlisted options need updating.
Copy file name to clipboardExpand all lines: i18n/qqq.json
+11-2Lines changed: 11 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -246,8 +246,17 @@
246
246
"maps-validator-message-nodesc": "Indicates that no parameter description is available",
247
247
"maps-config-invalid": "Heading shown above the list of errors when an edit to the MediaWiki:Maps JSON config page is rejected.",
248
248
"maps-config-error-invalid-json": "Error shown when the MediaWiki:Maps config is not a JSON object.",
249
-
"maps-config-error-not-object": "Error shown when a value that must be a JSON object is not. $1 is the location, e.g. \"leaflet\" or \"layerDefinitions\".",
250
-
"maps-config-error-unknown-key": "Error shown when the config contains an unrecognized key. $1 is the unknown key.",
249
+
"maps-config-error-not-object": "Error shown when a value that must be a JSON object is not. $1 is the location, e.g. \"general\" or \"leaflet.layerDefinitions\".",
250
+
"maps-config-error-unknown-key": "Error shown when the config contains an unrecognized group or key. $1 is the unknown key, e.g. \"general\" or \"general.mapWidth\".",
251
+
"maps-config-error-invalid-boolean": "Error shown when a setting that must be a boolean is not. $1 is the location, e.g. \"general.resizableByDefault\".",
252
+
"maps-config-error-invalid-integer": "Error shown when a setting that must be a whole number is not. $1 is the location, e.g. \"leaflet.defaultZoom\".",
253
+
"maps-config-error-integer-too-small": "Error shown when a whole-number setting is below its minimum. $1 is the location, $2 is the minimum.",
254
+
"maps-config-error-invalid-string": "Error shown when a setting that must be text is not. $1 is the location, e.g. \"general.defaultTitle\".",
255
+
"maps-config-error-invalid-enum": "Error shown when a setting is not one of its allowed values. $1 is the location, $2 is the comma-separated list of allowed values.",
256
+
"maps-config-error-invalid-enum-list": "Error shown when a setting is not a list of allowed values. $1 is the location, $2 is the comma-separated list of allowed values.",
257
+
"maps-config-error-invalid-dimension": "Error shown when a map size setting is not a valid dimension. $1 is the location, e.g. \"general.mapWidth\".",
258
+
"maps-config-error-invalid-number-map": "Error shown when the distance units setting is not a map of names to positive numbers. $1 is the location.",
259
+
"maps-config-error-invalid-language": "Error shown when the Google Maps language setting is not a valid language code. $1 is the location.",
251
260
"maps-config-error-invalid-layer-name": "Error shown when a custom Leaflet layer has an invalid name. $1 is the name.",
252
261
"maps-config-error-unknown-layer-key": "Error shown when a custom Leaflet layer definition has an unrecognized property. $1 is the layer name, $2 is the property.",
253
262
"maps-config-error-invalid-url": "Error shown when a custom Leaflet layer has no valid url. $1 is the layer name.",
0 commit comments