r109360 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r109359‎ | r109360 | r109361 >
Date:13:34, 18 January 2012
Author:maxsem
Status:deferred
Tags:geodata 
Comment:
Improved input validation with customizable warning level
Modified paths:
  • /trunk/extensions/GeoData/CoordinatesParserFunction.php (modified) (history)
  • /trunk/extensions/GeoData/GeoData.i18n.php (modified) (history)
  • /trunk/extensions/GeoData/GeoData.php (modified) (history)
  • /trunk/extensions/GeoData/tests/TagTest.php (modified) (history)

Diff [purge]

Index: trunk/extensions/GeoData/tests/TagTest.php
@@ -8,28 +8,49 @@
99 $GLOBALS['wgDefaultDim'] = 1000; // reset to default
1010 }
1111
12 - /**
13 - * @dataProvider getData
14 - */
15 - public function testTagParsing( $input, $expected ) {
 12+ private function setWarnings( $level ) {
 13+ global $wgGeoDataWarningLevel;
 14+ foreach ( array_keys( $wgGeoDataWarningLevel ) as $key ) {
 15+ $wgGeoDataWarningLevel[$key] = $level;
 16+ }
 17+ }
 18+
 19+ private function assertParse( $input, $expected ) {
1620 $p = new Parser();
1721 $opt = new ParserOptions();
1822 $out = $p->parse( $input, Title::newMainPage(), $opt );
1923 $this->assertTrue( isset( $out->geoData ) );
2024 if ( !$expected ) {
21 - $this->assertFalse( $out->geoData['primary'] );
22 - $this->assertEmpty( $out->geoData['secondary'] );
 25+ $this->assertEmpty( $out->geoData->getAll(),
 26+ 'Expected a failure but a result was found: ' . print_r( $out->geoData->getAll(), true )
 27+ );
2328 return;
2429 }
2530 $all = $out->geoData->getAll();
26 - $this->assertEquals( 1, count( $all ), 'A result was expected' );
 31+ $this->assertEquals( 1, count( $all ), 'A result was expected, but there was error: ' . strip_tags( $out->getText() ) );
2732 $coord = $all[0];
2833 foreach ( $expected as $field => $value ) {
2934 $this->assertEquals( $value, $coord->$field, "Checking field $field" );
3035 }
3136 }
3237
33 - public function getData() {
 38+ /**
 39+ * @dataProvider getLooseData
 40+ */
 41+ public function testLooseTagParsing( $input, $expected ) {
 42+ $this->setWarnings( 'none' );
 43+ $this->assertParse( $input, $expected );
 44+ }
 45+
 46+ /**
 47+ * @dataProvider getStrictData
 48+ */
 49+ public function testStrictTagParsing( $input, $expected ) {
 50+ $this->setWarnings( 'fail' );
 51+ $this->assertParse( $input, $expected );
 52+ }
 53+
 54+ public function getLooseData() {
3455 return array(
3556 // Basics
3657 array(
@@ -37,6 +58,14 @@
3859 array( 'lat' => 10, 'lon' => 20, 'globe' => 'earth', 'primary' => true ),
3960 ),
4061 array(
 62+ '{{#coordinates: 100|20|primary}}',
 63+ false,
 64+ ),
 65+ array(
 66+ '{{#coordinates: 10|2000|primary}}',
 67+ false,
 68+ ),
 69+ array(
4170 '{{#coordinates: 10| primary | 20}}',
4271 array( 'lat' => 10, 'lon' => 20, 'globe' => 'earth', 'primary' => true ),
4372 ),
@@ -105,4 +134,25 @@
106135 ),
107136 );
108137 }
 138+
 139+ public function getStrictData() {
 140+ return array(
 141+ array(
 142+ '{{#coordinates:10|20|globe:Moon dim:10_region:RUS-MOS}}',
 143+ false,
 144+ ),
 145+ array(
 146+ '{{#coordinates:10|20|globe:Moon dim:10_region:RU-}}',
 147+ false,
 148+ ),
 149+ array(
 150+ '{{#coordinates:10|20|globe:Moon dim:10|region=RU-longvalue}}',
 151+ false,
 152+ ),
 153+ array(
 154+ '{{#coordinates:10|20|globe:Moon dim:10_region:РУ-МОС}}',
 155+ false,
 156+ ),
 157+ );
 158+ }
109159 }
\ No newline at end of file
Index: trunk/extensions/GeoData/CoordinatesParserFunction.php
@@ -141,15 +141,29 @@
142142 }
143143
144144 private function applyTagArgs( Coord $coord ) {
145 - global $wgContLang, $wgTypeToDim, $wgDefaultDim;
146 - $result = Status::newGood();
 145+ global $wgContLang, $wgTypeToDim, $wgDefaultDim, $wgGeoDataWarningLevel, $wgGlobes ;
147146 $args = $this->named;
148147 $coord->primary = isset( $args['primary'] );
149148 $coord->globe = isset( $args['globe'] ) ? $wgContLang->lc( $args['globe'] ) : $wgDefaultGlobe;
 149+ if ( !isset( $wgGlobes[$coord->globe] ) ) {
 150+ if ( $wgGeoDataWarningLevel['unknown globe'] == 'fail' ) {
 151+ return Status::newFatal( 'geodata-bad-globe', $coord->globe );
 152+ } elseif ( $wgGeoDataWarningLevel['unknown globe'] == 'warn' ) {
 153+ $this->parser->addTrackingCategory( 'geodata-unknown-globe-category' );
 154+ }
 155+ }
150156 $coord->dim = $wgDefaultDim;
151157 if ( isset( $args['type'] ) ) {
152158 $coord->type = preg_replace( '/\(.*?\).*$/', '', $args['type'] );
153 - $coord->dim = isset( $wgTypeToDim[$coord->type] ) ? isset( $wgTypeToDim[$coord->type] ) : $wgDefaultDim;
 159+ if ( isset( $wgTypeToDim[$coord->type] ) ) {
 160+ $coord->dim = $wgTypeToDim[$coord->type];
 161+ } else {
 162+ if ( $wgGeoDataWarningLevel['unknown type'] == 'fail' ) {
 163+ return Status::newFatal( 'geodata-bad-type', $coord->type );
 164+ } elseif ( $wgGeoDataWarningLevel['unknown type'] == 'warn' ) {
 165+ $this->parser->addTrackingCategory( 'geodata-unknown-type-category' );
 166+ }
 167+ }
154168 }
155169 if ( isset( $args['scale'] ) ) {
156170 $coord->dim = $args['scale'] / 10;
@@ -163,14 +177,18 @@
164178 $coord->name = isset( $args['name'] ) ? $args['name'] : null;
165179 if ( isset( $args['region'] ) ) {
166180 $code = strtoupper( $args['region'] );
167 - if ( preg_match( '/([A-Z]{2})(?:-([A-Z0-9]{1,3}))?/', $code, $m ) ) {
 181+ if ( preg_match( '/^([A-Z]{2})(?:-([A-Z0-9]{1,3}))?$/', $code, $m ) ) {
168182 $coord->country = $m[1];
169183 $coord->region = isset( $m[2] ) ? $m[2] : null;
170184 } else {
171 - $result->warning( 'geodata-bad-region', $args['region'] ); //@todo: actually use this warning
 185+ if ( $wgGeoDataWarningLevel['invalid region'] == 'fail' ) {
 186+ return Status::newFatal( 'geodata-bad-region', $args['region'] );
 187+ } elseif ( $wgGeoDataWarningLevel['invalid region'] == 'warn' ) {
 188+ $this->parser->addTrackingCategory( 'geodata-unknown-region-category' );
 189+ }
172190 }
173191 }
174 - return $result;
 192+ return Status::newGood();
175193 }
176194
177195 private function parseGeoHackArgs( $str ) {
Index: trunk/extensions/GeoData/GeoData.i18n.php
@@ -16,10 +16,15 @@
1717 'geodata-bad-input' => 'Invalid arguments have been passed to the <nowiki>{{#coordinates:}}</nowiki> function',
1818 'geodata-bad-latitude' => '<nowiki>{{#coordinates:}}</nowiki>: invalid latitude',
1919 'geodata-bad-longitude' => '<nowiki>{{#coordinates:}}</nowiki>: invalid longitude',
 20+ 'geodata-bad-type' => '<nowiki>{{#coordinates:}}</nowiki>: unrecognised type "$1"',
 21+ 'geodata-bad-globe' => '<nowiki>{{#coordinates:}}</nowiki>: unrecognised globe "$1"',
2022 'geodata-bad-region' => '<nowiki>{{#coordinates:}}</nowiki>: invalid region code format',
2123 'geodata-multiple-primary' => '<nowiki>{{#coordinates:}}</nowiki>: cannot have more than one primary tag per page',
2224 'geodata-limit-exceeded' => 'The limit of $1 <nowiki>{{#coordinates:}}</nowiki> {{PLURAL:$1|tag|tags}} per page has been exceeded',
2325 'geodata-broken-tags-category' => 'Pages with malformed coordinate tags',
 26+ 'geodata-unknown-type-category' => 'Pages with unknown type of coordinates',
 27+ 'geodata-unknown-globe-category' => 'Pages with unknown globe value',
 28+ 'geodata-unknown-region-category' => 'Pages with invalid region value',
2429 'geodata-primary-coordinate' => 'primary',
2530 );
2631
@@ -30,6 +35,9 @@
3136 'geodata-desc' => '{{desc}}',
3237 'geodata-limit-exceeded' => '$1 is a number',
3338 'geodata-broken-tags-category' => 'Name of the tracking category',
 39+ 'geodata-unknown-type-category' => 'Name of the tracking category',
 40+ 'geodata-unknown-globe-category' => 'Name of the tracking category',
 41+ 'geodata-unknown-region-category' => 'Name of the tracking category',
3442 'geodata-primary-coordinate' => 'Localised name of parameter that makes <nowiki>{{#coordinates:}}</nowiki> tag primary',
3543 );
3644
Index: trunk/extensions/GeoData/GeoData.php
@@ -126,3 +126,15 @@
127127 unset( $east360 );
128128 unset( $west360 );
129129
 130+/**
 131+ * Controls what GeoData should do when it encounters some problem.
 132+ * Reaction type:
 133+ * - track - Add tracking category
 134+ * - fail - Consider the tag invalid, display message and add tracking category
 135+ * - none - Do nothing
 136+ */
 137+$wgGeoDataWarningLevel = array(
 138+ 'unknown type' => 'track',
 139+ 'unknown globe' => 'track',
 140+ 'invalid region' => 'track',
 141+);

Status & tagging log