r109047 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r109046‎ | r109047 | r109048 >
Date:17:45, 16 January 2012
Author:maxsem
Status:deferred (Comments)
Tags:geodata 
Comment:
IM ON UR MARS, VALIDATING UR COORDINATES
Modified paths:
  • /trunk/extensions/GeoData/ApiQueryGeoSearch.php (modified) (history)
  • /trunk/extensions/GeoData/CoordinatesParserFunction.php (modified) (history)
  • /trunk/extensions/GeoData/GeoData.body.php (modified) (history)
  • /trunk/extensions/GeoData/GeoData.php (modified) (history)
  • /trunk/extensions/GeoData/tests/ParseCoordTest.php (modified) (history)

Diff [purge]

Index: trunk/extensions/GeoData/tests/ParseCoordTest.php
@@ -7,17 +7,18 @@
88 /**
99 * @dataProvider getCases
1010 */
11 - public function testParseCoordinates( $parts, $result ) {
 11+ public function testParseCoordinates( $parts, $result, $globe = 'earth' ) {
1212 $formatted = '"' . implode( $parts, '|' ) . '"';
13 - $s = GeoData::parseCoordinates( $parts );
 13+ $s = GeoData::parseCoordinates( $parts, $globe );
1414 $val = $s->value;
1515 if ( $result === false ) {
1616 $this->assertFalse( $s->isGood(), "Parsing of $formatted was expected to fail" );
1717 } else {
18 - $this->assertTrue( $s->isGood(), "Parsing of $formatted was expected to suceed, but it failed" );
 18+ $msg = $s->isGood() ? '' : $s->getWikiText();
 19+ $this->assertTrue( $s->isGood(), "Parsing of $formatted was expected to succeed, but it failed: $msg" );
1920 $this->assertTrue( $val->equalsTo( $result ),
20 - "Parsing of $formatted was expected to yield something close to"
21 - . " ({$result->lat}, {$result->lon}), but yielded ({$val->lat}, {$val->lon})"
 21+ "Parsing of $formatted was expected to yield something close to"
 22+ . " ({$result->lat}, {$result->lon}), but yielded ({$val->lat}, {$val->lon})"
2223 );
2324 }
2425 }
@@ -57,6 +58,21 @@
5859 array( array( 1, 2, 3, 'N', 'E' ), false ),
5960 array( array( 1, 2, 3, 'N', 1, 'E' ), false ),
6061 array( array( 1, 2, 3, 'N', 1, 2, 'E' ), false ),
 62+ // coordinate validation (Earth)
 63+ array( array( -90, 180 ), new Coord( -90, 180 ) ),
 64+ array( array( 90.0000001, -180.00000001 ), false ),
 65+ array( array( 90, 1, 180, 0 ), false ),
 66+ array( array( 10, -1, 20, 0 ), false ),
 67+ array( array( 25, 60, 10, 0 ), false ),
 68+ array( array( 25, 0, 0, 10, 0, 60 ), false ),
 69+ // @todo: only the last component of the coordinate should be non-integer
 70+ //array( array( 10.5, 0, 20, 0 ), false ),
 71+ //array( array( 10, 30.5, 0, 20, 0, 0 ), false ),
 72+ // coordinate validation and normalisation (non-Earth)
 73+ array( array( 10, 20 ), new Coord( 10, 20 ), 'mars' ),
 74+ array( array( 110, 20 ), false, 'mars' ),
 75+ array( array( 47, 0, 'S', 355, 3, 'W' ), new Coord( -47, 4.95 ), 'mars' ), // Asimov Crater
 76+ array( array( 68, 'S', 357, 'E' ), new Coord( -68, 357 ), 'venus' ), // Quetzalpetlatl Corona
6177 );
6278 }
6379 }
\ No newline at end of file
Index: trunk/extensions/GeoData/CoordinatesParserFunction.php
@@ -58,10 +58,11 @@
5959 $this->addArg( $value );
6060 }
6161 }
62 - $status = GeoData::parseCoordinates( $this->unnamed );
 62+ $this->parseTagArgs();
 63+ $status = GeoData::parseCoordinates( $this->unnamed, $this->named['globe'] );
6364 if ( $status->isGood() ) {
6465 $coord = $status->value;
65 - $status = $this->parseTagArgs( $coord );
 66+ $status = $this->applyTagArgs( $coord );
6667 if ( $status->isGood() ) {
6768 $status = $this->applyCoord( $coord );
6869 if ( $status->isGood() ) {
@@ -128,14 +129,21 @@
129130 *
130131 * @param Coord $coord
131132 */
132 - private function parseTagArgs( Coord $coord ) {
133 - global $wgDefaultGlobe, $wgContLang, $wgTypeToDim, $wgDefaultDim;
 133+ private function parseTagArgs() {
 134+ global $wgDefaultGlobe, $wgContLang;
 135+ // fear not of overwriting the stuff we've just received from the geohack param, it has minimum precedence
 136+ if ( isset( $this->named['geohack'] ) ) {
 137+ $this->named = array_merge( $this->parseGeoHackArgs( $this->named['geohack'] ), $this->named );
 138+ }
 139+ $this->named['globe'] = isset( $this->named['globe'] )
 140+ ? $wgContLang->lc( $this->named['globe'] )
 141+ : $wgDefaultGlobe;
 142+ }
 143+
 144+ private function applyTagArgs( Coord $coord ) {
 145+ global $wgContLang, $wgTypeToDim, $wgDefaultDim;
134146 $result = Status::newGood();
135147 $args = $this->named;
136 - // fear not of overwriting the stuff we've just received from the geohack param, it has minimum precedence
137 - if ( isset( $args['geohack'] ) ) {
138 - $args = array_merge( $this->parseGeoHackArgs( $args['geohack'] ), $args );
139 - }
140148 $coord->primary = isset( $args['primary'] );
141149 $coord->globe = isset( $args['globe'] ) ? $wgContLang->lc( $args['globe'] ) : $wgDefaultGlobe;
142150 $coord->dim = $wgDefaultDim;
Index: trunk/extensions/GeoData/ApiQueryGeoSearch.php
@@ -30,7 +30,7 @@
3131 $this->requireOnlyOneParameter( $params, 'coord', 'page' );
3232 if ( isset( $params['coord'] ) ) {
3333 $arr = explode( '|', $params['coord'] );
34 - if ( count( $arr ) != 2 || !GeoData::validateCoord( $arr[0], $arr[1] ) ) {
 34+ if ( count( $arr ) != 2 || !GeoData::validateCoord( $arr[0], $arr[1], $params['globe'] ) ) {
3535 $this->dieUsage( 'Invalid coordinate provided', '_invalid-coord' );
3636 }
3737 $lat = $arr[0];
Index: trunk/extensions/GeoData/GeoData.body.php
@@ -7,11 +7,16 @@
88 * @param type $lon
99 * @return Boolean: Whether the coordinate is valid
1010 */
11 - public static function validateCoord( $lat, $lon ) {
12 - return is_numeric( $lat )
13 - && is_numeric( $lon )
14 - && abs( $lat ) <= 90
15 - && abs( $lon ) <= 180;
 11+ public static function validateCoord( $lat, $lon, $globe ) {
 12+ global $wgGlobes;
 13+ if ( !is_numeric( $lat ) || !is_numeric( $lon ) || abs( $lat ) > 90 ) {
 14+ return false;
 15+ }
 16+ if ( !isset( $wgGlobes[$globe] ) ) {
 17+ return abs( $lon ) <= 360;
 18+ } else {
 19+ return $lon >= $wgGlobes[$globe]['min'] && $lon <= $wgGlobes[$globe]['max'];
 20+ }
1621 }
1722
1823 /**
@@ -50,11 +55,12 @@
5156 * Parses coordinates
5257 * See https://en.wikipedia.org/wiki/Template:Coord for sample inputs
5358 *
54 - * @param String $str:
 59+ * @param Array $parts: Array of coordinate components
 60+ * @param String $globe: Globe name
5561 * @returns Status: Status object, in case of success its value is a Coord object.
5662 */
57 - public static function parseCoordinates( $parts ) {
58 - global $wgContLang;
 63+ public static function parseCoordinates( $parts, $globe ) {
 64+ global $wgContLang, $wgGlobes;
5965
6066 $count = count( $parts );
6167 if ( !is_array( $parts ) || $count < 2 || $count > 8 || ( $count % 2 ) ) {
@@ -67,7 +73,16 @@
6874 if ( $lat === false ) {
6975 return Status::newFatal( 'geodata-bad-latitude' );
7076 }
71 - $lon = self::parseOneCoord( $lonArr, $coordInfo['lon'] );
 77+ $lonInfo = isset( $wgGlobes[$globe] )
 78+ ? $wgGlobes[$globe]
 79+ : array(
 80+ 'min' => -360,
 81+ 'mid' => 0,
 82+ 'max' => 360,
 83+ 'abbr' => array( 'E' => 1, 'W' => -1 ),
 84+ 'wrap' => true,
 85+ );
 86+ $lon = self::parseOneCoord( $lonArr, $lonInfo );
7287 if ( $lon === false ) {
7388 return Status::newFatal( 'geodata-bad-longitude' );
7489 }
@@ -96,8 +111,8 @@
97112 }
98113 }
99114 $part = $wgContLang->parseFormattedNumber( $part );
100 - $min = $i == 0 ? -$coordInfo['range'] : 0;
101 - $max = $i == 0 ? $coordInfo['range'] : 59.999999;
 115+ $min = $i == 0 ? $coordInfo['min'] : 0;
 116+ $max = $i == 0 ? $coordInfo['max'] : 59.999999;
102117 if ( !is_numeric( $part )
103118 || $part < $min
104119 || $part > $max ) {
@@ -106,7 +121,10 @@
107122 $value += $part * $multiplier * GeoMath::sign( $value );
108123 $multiplier /= 60;
109124 }
110 - if ( abs( $value ) > $coordInfo['range'] ) {
 125+ if ( $coordInfo['wrap'] && $value < 0 ) {
 126+ $value = $coordInfo['max'] + $value;
 127+ }
 128+ if ( $value < $coordInfo['min'] || $value > $coordInfo['max'] ) {
111129 return false;
112130 }
113131 return $value;
@@ -122,17 +140,7 @@
123141 private static function parseSuffix( $str, $coordInfo ) {
124142 global $wgContLang;
125143 $str = $wgContLang->uc( trim( $str ) );
126 - foreach ( $coordInfo['-'] as $suffix ) {
127 - if ( $suffix == $str ) {
128 - return -1;
129 - }
130 - }
131 - foreach ( $coordInfo['+'] as $suffix ) {
132 - if ( $suffix == $str ) {
133 - return 1;
134 - }
135 - }
136 - return 0;
 144+ return isset( $coordInfo['abbr'][$str] ) ? $coordInfo['abbr'][$str] : 0;
137145 }
138146
139147 public static function getCoordInfo() {
@@ -141,19 +149,16 @@
142150 if ( !$result ) {
143151 $result = array(
144152 'lat' => array(
145 - 'range' => 90,
146 - '+' => array( 'N' ),
147 - '-' => array( 'S' ),
 153+ 'min' => -90,
 154+ 'mid' => 0,
 155+ 'max' => 90,
 156+ 'abbr' => array( 'N' => 1, 'S' => -1 ),
 157+ 'wrap' => false,
148158 ),
149 - 'lon' => array(
150 - 'range' => 180,
151 - '+' => array( 'E' ),
152 - '-' => array( 'W' ),
153 - ),
154159 'primary' => array( 'primary' ),
155160 );
156161 if ( $wgContLang->getCode() != 'en' ) {
157 - $result['primary'][] = wfMessage( 'geodata-primary-coordinate' )->plain();
 162+ $result['primary'][] = wfMessage( 'geodata-primary-coordinate' )->inContentLanguage()->plain();
158163 }
159164 $result['primary'] = array_flip( $result['primary'] );
160165 }
Index: trunk/extensions/GeoData/GeoData.php
@@ -82,3 +82,47 @@
8383 * Default value of dim if it is unknown
8484 */
8585 $wgDefaultDim = 1000;
 86+
 87+$earth = array( 'min' => -180, 'mid' => 0, 'max' => 180, 'abbr' => array( 'E' => +1, 'W' => -1 ), 'wrap' => false );
 88+$east360 = array( 'min' => 0, 'mid' => 180, 'max' => 360, 'abbr' => array( 'E' => +1, 'W' => -1 ), 'wrap' => true );
 89+$west360 = array( 'min' => 0, 'mid' => 180, 'max' => 360, 'abbr' => array( 'E' => -1, 'W' => +1 ), 'wrap' => true );
 90+
 91+/**
 92+ * Description of coordinate systems, mostly taken from http://planetarynames.wr.usgs.gov/TargetCoordinates
 93+ */
 94+$wgGlobes = array(
 95+ 'earth' => $earth,
 96+ 'mercury' => $west360,
 97+ 'venus' => $east360,
 98+ 'moon' => $earth,
 99+ 'mars' => $east360,
 100+ 'phobos' => $west360,
 101+ 'deimos' => $west360,
 102+ //'ceres' => ???,
 103+ //'vesta' => ???,
 104+ 'ganymede' => $west360,
 105+ 'callisto' => $west360,
 106+ 'io' => $west360,
 107+ 'europa' => $west360,
 108+ 'mimas' => $west360,
 109+ 'enceladus' => $west360,
 110+ 'tethys' => $west360,
 111+ 'dione' => $west360,
 112+ 'rhea' => $west360,
 113+ 'titan' => $west360,
 114+ 'hyperion' => $west360,
 115+ 'iapetus' => $west360,
 116+ 'phoebe' => $west360,
 117+ 'miranda' => $east360,
 118+ 'ariel' => $east360,
 119+ 'umbriel' => $east360,
 120+ 'titania' => $east360,
 121+ 'oberon' => $east360,
 122+ 'triton' => $east360,
 123+ 'pluto' => $east360, // ???
 124+);
 125+
 126+unset( $earth );
 127+unset( $east360 );
 128+unset( $west360 );
 129+

Comments

#Comment by Reedy (talk | contribs)   18:51, 16 January 2012

Have the Russians invented portals? Or are they sponsoring a WMF rocket to mars? It's going to be very hard for us to test this

#Comment by MaxSem (talk | contribs)   19:17, 16 January 2012

No, cuz I've included unit tests.

Status & tagging log