jenkins-bot has submitted this change and it was merged. Change subject: Add "page" external data support ......................................................................
Add "page" external data support Bug: T137930 Change-Id: I933fdb5de26e905e6e7fa6e3dbfd0293c9267b53 --- M i18n/en.json M i18n/qqq.json M includes/SimpleStyleParser.php M lib/wikimedia-mapdata.js M schemas/geojson.json M tests/parserTests.txt M tests/phpunit/ValidationTest.php A tests/phpunit/data/bad-schemas/58-externaldata.json D tests/phpunit/data/bad-schemas/58-featurecollection-non-nestable.json A tests/phpunit/data/bad-schemas/59-externaldata.json D tests/phpunit/data/bad-schemas/59-featurecollection-non-nestable.json M tests/phpunit/data/bad-schemas/60-featurecollection-non-nestable.json M tests/phpunit/data/bad-schemas/61-featurecollection-non-nestable.json A tests/phpunit/data/bad-schemas/62-featurecollection-non-nestable.json A tests/phpunit/data/bad-schemas/63-featurecollection-non-nestable.json M tests/phpunit/data/good-schemas/08-externaldata.json 16 files changed, 168 insertions(+), 88 deletions(-) Approvals: MaxSem: Looks good to me, approved jenkins-bot: Verified diff --git a/i18n/en.json b/i18n/en.json index 04d61d9..193add7 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -27,7 +27,7 @@ "kartographer-error-bad_attr": "Attribute \"$1\" has an invalid value", "kartographer-error-bad_data": "The JSON content is not valid GeoJSON+simplestyle", "kartographer-error-latlon": "Either both \"latitude\" and \"longitude\" parameters should be supplied or neither of them", - "kartographer-error-service-name": "Invalid cartographic service \"$1\"", + "kartographer-error-title": "Title \"$1\" is not a valid map data page", "kartographer-tracking-category": "{{#switch:{{NAMESPACE}}|{{ns:File}}=Files|#default=Pages}} with maps", "kartographer-tracking-category-desc": "The page includes a map", "kartographer-coord-combined": "$1 $2", diff --git a/i18n/qqq.json b/i18n/qqq.json index eb386fd..06a721f 100644 --- a/i18n/qqq.json +++ b/i18n/qqq.json @@ -31,7 +31,7 @@ "kartographer-error-bad_attr": "Error shown instead of a map in case of a problem with parameters.\n\nParameters:\n* $1 - non-localized attribute name, such as 'height', 'latitude', etc", "kartographer-error-bad_data": "This error is shown if the content of the tag is syntactically valid JSON however it does not adhere to GeoJSON and simplestyle specifications", "kartographer-error-latlon": "Error shown by <maplink> or <mapframe> when certain parameters are incorrect", - "kartographer-error-service-name": "Error shown by <maplink> or <mapframe>. Parameters:\n* $1 - service name.", + "kartographer-error-title": "Error shown by <maplink> or <mapframe>. Parameters:\n* $1 - page title.", "kartographer-tracking-category": "Name of the tracking category", "kartographer-tracking-category-desc": "Description on [[Special:TrackingCategories]] for the {{msg-mw|kartographer-tracking-category}} tracking category.", "kartographer-coord-combined": "{{optional}}\nJoins two parts of geogrpahical coordinates. $1 and $2 are latitude and longitude, respectively.", diff --git a/includes/SimpleStyleParser.php b/includes/SimpleStyleParser.php index d773ef2..a688501 100644 --- a/includes/SimpleStyleParser.php +++ b/includes/SimpleStyleParser.php @@ -3,7 +3,10 @@ namespace Kartographer; use FormatJson; +use JsonConfig\JCMapDataContent; +use JsonConfig\JCSingleton; use JsonSchema\Validator; +use LogicException; use MediaWiki\MediaWikiServices; use Parser; use PPFrame; @@ -15,8 +18,6 @@ */ class SimpleStyleParser { private static $parsedProps = [ 'title', 'description' ]; - - private static $services = [ 'geoshape', 'geoline', 'geomask' ]; /** @var Parser */ private $parser; @@ -139,7 +140,7 @@ * @param mixed $json * @return Status */ - private function validateContent( $json ) { + protected function validateContent( $json ) { $schema = self::loadSchema(); $validator = new Validator(); $validator->check( $json, $schema ); @@ -158,7 +159,7 @@ * * @param object|array $json */ - private function sanitize( &$json ) { + protected function sanitize( &$json ) { if ( is_array( $json ) ) { foreach ( $json as &$element ) { $this->sanitize( $element ); @@ -185,7 +186,7 @@ * @param array $json * @return Status */ - private function normalize( array &$json ) { + protected function normalize( array &$json ) { $status = Status::newGood(); foreach ( $json as &$object ) { if ( $object->type === 'ExternalData' ) { @@ -204,38 +205,59 @@ * @return Status */ private function normalizeExternalData( &$object ) { - if ( !in_array( $object->service, self::$services ) ) { - return Status::newFatal( 'kartographer-error-service-name', $object->service ); - } $ret = (object)[ 'type' => 'ExternalData', 'service' => $object->service, ]; - $query = [ - 'getgeojson' => 1 - ]; + switch ( $object->service ) { + case 'geoshape': + case 'geoline': + case 'geomask': + $query = [ 'getgeojson' => 1 ]; + if ( property_exists( $object, 'ids' ) ) { + $query['ids'] = + is_array( $object->ids ) ? join( ',', $object->ids ) + : preg_replace( '/\s*,\s*/', ',', $object->ids ); + } + if ( property_exists( $object, 'query' ) ) { + $query['query'] = $object->query; + } + // 'geomask' service is the same as inverted geoshape service + // Kartotherian does not support it, request it as geoshape + $service = $object->service === 'geomask' ? 'geoshape' : $object->service; - if ( property_exists( $object, 'ids' ) ) { - $query['ids'] = is_array( $object->ids ) - ? join( ',', $object->ids ) - : preg_replace( '/\s*,\s*/', ',', $object->ids ); - } - if ( property_exists( $object, 'query' ) ) { - $query['query'] = $object->query; - } + $ret->url = "{$this->mapService}/{$service}?" . wfArrayToCgi( $query ); + if ( property_exists( $object, 'properties' ) ) { + $ret->properties = $object->properties; + } + break; - // 'geomask' service is the same as inverted geoshape service - // Kartotherian does not support it, request it as geoshape - $service = $object->service === 'geomask' ? 'geoshape' : $object->service; - $ret->url = "{$this->mapService}/{$service}?" . wfArrayToCgi( $query ); - if ( property_exists( $object, 'properties' ) ) { - $ret->properties = $object->properties; + case 'page': + if ( !class_exists( 'JsonConfig\\JCSingleton' ) ) { + return Status::newFatal( 'kartographer-error-service-name', $object->service ); + } + $jct = JCSingleton::parseTitle( $object->title, NS_DATA ); + if ( !$jct || JCSingleton::getContentClass( $jct->getConfig()->model ) !== + JCMapDataContent::class + ) { + return Status::newFatal( 'kartographer-error-title', $object->title ); + } + $query = [ + 'format' => 'json', + 'formatversion' => '2', + 'action' => 'jsondata', + 'title' => $jct->getText(), + ]; + $ret->url = wfScript( 'api' ) . '?' . wfArrayToCgi( $query ); + break; + + default: + throw new LogicException( "Unexpected service name '{$object->service}'" ); } $object = $ret; - return Status::newGood(); } diff --git a/lib/wikimedia-mapdata.js b/lib/wikimedia-mapdata.js index d1652f9..add9dfa 100644 --- a/lib/wikimedia-mapdata.js +++ b/lib/wikimedia-mapdata.js @@ -195,6 +195,13 @@ switch ( data.service ) { + case 'page': + if ( geodata.jsondata && geodata.jsondata.data ) { + extend( data, geodata.jsondata.data ); + } + // FIXME: error reporting, at least to console.log + break; + case 'geomask': // Mask-out the entire world 10 times east and west, // and add each result geometry as a hole @@ -255,6 +262,8 @@ if ( mwMsg ) { group.parseAttribution(); } + }, function () { + group.failed = true; } ); return group.promise; @@ -268,6 +277,10 @@ uri = mwUri( group.geoJSON.url ); switch ( group.geoJSON.service ) { + case 'page': + // FIXME: add link to commons page + break; + case 'geoshape': case 'geoline': if ( uri.query.query ) { @@ -471,6 +484,8 @@ return group.parse( apiGeoJSON ).then( function ( group ) { return group.fetchExternalGroups(); } ); + }, function () { + group.failed = true; } ); return group.promise; }; @@ -551,7 +566,11 @@ } for ( i = 0; i < groupIds.length; i++ ) { group = DataStore$$1.get( groupIds[ i ] ) || DataStore$$1.add( new InternalGroup( groupIds[ i ] ) ); - promises.push( group.fetch() ); + /* jshint loopfunc:true */ + promises.push( wrappers.createPromise( function ( resolve ) { + group.fetch().then( resolve, resolve ); + } ) ); + /* jshint loopfunc:false */ } DataLoader$$1.fetch(); @@ -564,7 +583,7 @@ for ( i = 0; i < groupIds.length; i++ ) { group = DataStore$$1.get( groupIds[ i ] ); - if ( !wrappers.isEmptyObject( group.getGeoJSON() ) ) { + if ( group.failed || !wrappers.isEmptyObject( group.getGeoJSON() ) ) { groupList = groupList.concat( group ); } groupList = groupList.concat( group.externals ); diff --git a/schemas/geojson.json b/schemas/geojson.json index e750152..a6092a6 100644 --- a/schemas/geojson.json +++ b/schemas/geojson.json @@ -157,30 +157,44 @@ "description": "WMF extension - reference to external geometries", "required": [ "type", "service" ], - "anyOf": [ - { "required": [ "query" ] }, - { "required": [ "ids" ] } + "oneOf": [ + { + "required": [ "title" ], + "properties": { + "service": { "enum": [ "page" ] }, + "title": { "type": "string" } + } + }, + { + "anyOf": [ + { "required": [ "query" ] }, + { "required": [ "ids" ] } + ], + "properties": { + "service": { "enum": [ "geoshape", "geoline", "geomask" ] }, + "query": { "type": "string" }, + "ids": { + "oneOf": [ + { + "type": "array", + "items": { + "type": "string", + "pattern": "^Q[1-9]\\d{0,19}$" + } + }, + { + "type": "string", + "pattern": "^Q[1-9]\\d{0,19}(\\s*,\\s*Q[1-9]\\d{0,19})*$" + } + ] + } + } + } ], "properties": { "type": { "enum": [ "ExternalData" ] }, "service": { "type": "string" }, - "query": { "type": "string" }, - "ids": { - "oneOf": [ - { - "type": "array", - "items": { - "type": "string", - "pattern": "^Q[1-9]\\d{0,19}$" - } - }, - { - "type": "string", - "pattern": "^Q[1-9]\\d{0,19}(\\s*,\\s*Q[1-9]\\d{0,19})*$" - } - ] - }, "properties": { "$ref": "#/definitions/simplestyle" } } }, diff --git a/tests/parserTests.txt b/tests/parserTests.txt index ee40be5..49e1ffb 100644 --- a/tests/parserTests.txt +++ b/tests/parserTests.txt @@ -392,10 +392,6 @@ ] </maplink> !! result -<div class="mw-kartographer-error"><p><maplink> problems: -</p> -<ul><li> Invalid cartographic service "fail"</li> -<li> Invalid cartographic service "lulzifier"</li></ul> -</div> +<div class="mw-kartographer-error"><maplink>: The JSON content is not valid GeoJSON+simplestyle</div> !! end diff --git a/tests/phpunit/ValidationTest.php b/tests/phpunit/ValidationTest.php index ca520df..391fcbc 100644 --- a/tests/phpunit/ValidationTest.php +++ b/tests/phpunit/ValidationTest.php @@ -6,6 +6,7 @@ use MediaWikiTestCase; use Parser; use ParserOptions; +use Status; use Title; /** @@ -27,7 +28,7 @@ $options = new ParserOptions(); $title = Title::newMainPage(); $parser->startExternalParse( $title, $options, Parser::OT_HTML ); - $validator = new SimpleStyleParser( $parser ); + $validator = new MockSimpleStyleParser( $parser ); $file = $this->basePath . '/' . $fileName; $content = file_get_contents( $file ); @@ -59,3 +60,12 @@ return $result; } } + +class MockSimpleStyleParser extends SimpleStyleParser { + protected function sanitize( &$json ) { + } + + protected function normalize( array &$json ) { + return Status::newGood( $json ); + } +} diff --git a/tests/phpunit/data/bad-schemas/58-externaldata.json b/tests/phpunit/data/bad-schemas/58-externaldata.json new file mode 100644 index 0000000..ca3ba70 --- /dev/null +++ b/tests/phpunit/data/bad-schemas/58-externaldata.json @@ -0,0 +1,7 @@ +[ + { + "type": "ExternalData", + "service": "geoline", + "title": "foo" + } +] diff --git a/tests/phpunit/data/bad-schemas/58-featurecollection-non-nestable.json b/tests/phpunit/data/bad-schemas/58-featurecollection-non-nestable.json deleted file mode 100644 index 9190b11..0000000 --- a/tests/phpunit/data/bad-schemas/58-featurecollection-non-nestable.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "type": "FeatureCollection", - "features": [ - { - "type": "FeatureCollection", - "features": [] - } - ] -} diff --git a/tests/phpunit/data/bad-schemas/59-externaldata.json b/tests/phpunit/data/bad-schemas/59-externaldata.json new file mode 100644 index 0000000..e07073d --- /dev/null +++ b/tests/phpunit/data/bad-schemas/59-externaldata.json @@ -0,0 +1,7 @@ +[ + { + "type": "ExternalData", + "service": "page", + "query": "foo" + } +] diff --git a/tests/phpunit/data/bad-schemas/59-featurecollection-non-nestable.json b/tests/phpunit/data/bad-schemas/59-featurecollection-non-nestable.json deleted file mode 100644 index c1fe860..0000000 --- a/tests/phpunit/data/bad-schemas/59-featurecollection-non-nestable.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "type": "FeatureCollection", - "features": [ - { - "type": "Feature", - "geometry": { - "type": "FeatureCollection", - "features": [] - } - } - ] -} diff --git a/tests/phpunit/data/bad-schemas/60-featurecollection-non-nestable.json b/tests/phpunit/data/bad-schemas/60-featurecollection-non-nestable.json index aa17859..9190b11 100644 --- a/tests/phpunit/data/bad-schemas/60-featurecollection-non-nestable.json +++ b/tests/phpunit/data/bad-schemas/60-featurecollection-non-nestable.json @@ -2,13 +2,8 @@ "type": "FeatureCollection", "features": [ { - "type": "GeometryCollection", - "geometries": [ - { - "type": "FeatureCollection", - "features": [] - } - ] + "type": "FeatureCollection", + "features": [] } ] } diff --git a/tests/phpunit/data/bad-schemas/61-featurecollection-non-nestable.json b/tests/phpunit/data/bad-schemas/61-featurecollection-non-nestable.json index 9368a9b..c1fe860 100644 --- a/tests/phpunit/data/bad-schemas/61-featurecollection-non-nestable.json +++ b/tests/phpunit/data/bad-schemas/61-featurecollection-non-nestable.json @@ -1,7 +1,12 @@ { - "type": "Feature", - "geometry": { - "type": "FeatureCollection", - "features": [] - } + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "type": "FeatureCollection", + "features": [] + } + } + ] } diff --git a/tests/phpunit/data/bad-schemas/62-featurecollection-non-nestable.json b/tests/phpunit/data/bad-schemas/62-featurecollection-non-nestable.json new file mode 100644 index 0000000..aa17859 --- /dev/null +++ b/tests/phpunit/data/bad-schemas/62-featurecollection-non-nestable.json @@ -0,0 +1,14 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "GeometryCollection", + "geometries": [ + { + "type": "FeatureCollection", + "features": [] + } + ] + } + ] +} diff --git a/tests/phpunit/data/bad-schemas/63-featurecollection-non-nestable.json b/tests/phpunit/data/bad-schemas/63-featurecollection-non-nestable.json new file mode 100644 index 0000000..9368a9b --- /dev/null +++ b/tests/phpunit/data/bad-schemas/63-featurecollection-non-nestable.json @@ -0,0 +1,7 @@ +{ + "type": "Feature", + "geometry": { + "type": "FeatureCollection", + "features": [] + } +} diff --git a/tests/phpunit/data/good-schemas/08-externaldata.json b/tests/phpunit/data/good-schemas/08-externaldata.json index 945069b..24e1936 100644 --- a/tests/phpunit/data/good-schemas/08-externaldata.json +++ b/tests/phpunit/data/good-schemas/08-externaldata.json @@ -74,5 +74,10 @@ "service": "geomask", "query": "lalala", "ids": "Q1" + }, + { + "type": "ExternalData", + "service": "page", + "title": "lalala" } ] -- To view, visit https://gerrit.wikimedia.org/r/320153 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I933fdb5de26e905e6e7fa6e3dbfd0293c9267b53 Gerrit-PatchSet: 11 Gerrit-Project: mediawiki/extensions/Kartographer Gerrit-Branch: master Gerrit-Owner: Yurik <yu...@wikimedia.org> Gerrit-Reviewer: MaxSem <maxsem.w...@gmail.com> Gerrit-Reviewer: Siebrand <siebr...@kitano.nl> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits