Henning Snater has uploaded a new change for review. https://gerrit.wikimedia.org/r/67976
Change subject: Added precision detection to the GeoCoordinate parsers ...................................................................... Added precision detection to the GeoCoordinate parsers Change-Id: I7297d8b9b8e9f8cf39b44f11b38016f19236c541 --- M ValueParsers/includes/parsers/DdCoordinateParser.php M ValueParsers/includes/parsers/DmCoordinateParser.php M ValueParsers/includes/parsers/DmsCoordinateParser.php M ValueParsers/includes/parsers/FloatCoordinateParser.php M ValueParsers/tests/includes/parsers/DdCoordinateParserTest.php M ValueParsers/tests/includes/parsers/DmCoordinateParserTest.php M ValueParsers/tests/includes/parsers/DmsCoordinateParserTest.php M ValueParsers/tests/includes/parsers/FloatCoordinateParserTest.php M ValueParsers/tests/includes/parsers/GeoCoordinateParserTest.php 9 files changed, 236 insertions(+), 83 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/DataValues refs/changes/76/67976/1 diff --git a/ValueParsers/includes/parsers/DdCoordinateParser.php b/ValueParsers/includes/parsers/DdCoordinateParser.php index b0d4e32..bd80b7a 100644 --- a/ValueParsers/includes/parsers/DdCoordinateParser.php +++ b/ValueParsers/includes/parsers/DdCoordinateParser.php @@ -30,6 +30,7 @@ * * @licence GNU GPL v2+ * @author Jeroen De Dauw < [email protected] > + * @author H. Snater < [email protected] > */ class DdCoordinateParser extends StringValueParser { @@ -101,17 +102,25 @@ $latitude = $this->getParsedCoordinate( $latitude ); $longitude = $this->getParsedCoordinate( $longitude ); - return new GeoCoordinateValue( $latitude, $longitude ); + $precision = min( $latitude['precision'], $longitude['precision'] ); + + return new GeoCoordinateValue( + $latitude['coordinate'], + $longitude['coordinate'], + null, + $precision + ); } /** - * Parsers a single coordinate (either latitude or longitude) and returns it as a float. + * Parses a coordinate segment (either latitude or longitude) and returns it as a float along + * with the coordinate precision detected. * * @since 0.1 * * @param string $coordinate * - * @return float + * @return array */ protected function getParsedCoordinate( $coordinate ) { $coordinate = $this->resolveDirection( $coordinate ); @@ -191,16 +200,42 @@ } /** - * Takes a set of coordinates in Decimal Degree representation, and returns them in float representation. + * Takes a coordinate segment in Decimal Degree representation and returns it in float + * representation along with the segment precision detected. * * @since 0.1 * * @param string $coordinate * - * @return float + * @return array */ protected function parseDDCoordinate( $coordinate ) { - return (float)str_replace( $this->getOption( self::OPT_DEGREE_SYMBOL ), '', $coordinate ); + $coordinate = (float)str_replace( $this->getOption( self::OPT_DEGREE_SYMBOL ), '', $coordinate ); + return array( + 'coordinate' => $coordinate, + 'precision' => $this->detectPrecision( $coordinate ), + ); + } + + /** + * Detects a number's precision. + * + * @since 0.1 + * + * @param float $number + * + * @return int|float + */ + protected function detectPrecision( $number ) { + $split = explode( '.', $number ); + + $precision = 1; + + if( isset( $split[1] ) ) { + $precision = pow( 10, -1 * strlen( $split[1] ) ); + } + + return $precision; } /** diff --git a/ValueParsers/includes/parsers/DmCoordinateParser.php b/ValueParsers/includes/parsers/DmCoordinateParser.php index 1aed2c1..c808005 100644 --- a/ValueParsers/includes/parsers/DmCoordinateParser.php +++ b/ValueParsers/includes/parsers/DmCoordinateParser.php @@ -30,6 +30,7 @@ * * @licence GNU GPL v2+ * @author Jeroen De Dauw < [email protected] > + * @author H. Snater < [email protected] > */ class DmCoordinateParser extends StringValueParser { @@ -103,17 +104,25 @@ $latitude = $this->getParsedCoordinate( $latitude ); $longitude = $this->getParsedCoordinate( $longitude ); - return new GeoCoordinateValue( $latitude, $longitude ); + $precision = min( $latitude['precision'], $longitude['precision'] ); + + return new GeoCoordinateValue( + $latitude['coordinate'], + $longitude['coordinate'], + null, + $precision + ); } /** - * Parsers a single coordinate (either latitude or longitude) and returns it as a float. + * Parses a coordinate segment (either latitude or longitude) and returns it as a float along + * with the coordinate precision detected. * * @since 0.1 * * @param string $coordinate * - * @return float + * @return array */ protected function getParsedCoordinate( $coordinate ) { $coordinate = $this->resolveDirection( $coordinate ); @@ -196,13 +205,14 @@ } /** - * Takes a set of coordinates in Decimal Minute representation, and returns them in float representation. + * Takes a coordinate segment in Decimal Minute representation and returns it in float + * representation along with the segment precision detected. * * @since 0.1 * * @param string $coordinate * - * @return float + * @return array */ protected function parseDMCoordinate( $coordinate ) { $isNegative = $coordinate{0} == '-'; @@ -221,10 +231,45 @@ $coordinate *= -1; } - return (float)$coordinate; + return array( + 'coordinate' => ( float )$coordinate, + 'precision' => $this->detectPrecision( $minutes ), + ); } /** + * Detects the precision of given minutes. + * + * @since 0.1 + * + * @param int|float $minutes + * + * @return float + */ + protected function detectPrecision( $minutes ) { + $precision = 1 / 60; + + // The minute may be a float; In order to detect a proper precision, we convert the minutes + // to seconds. + $minutesSplit = explode( '.', $minutes ); + + if( isset( $minutesSplit[1] ) ) { + $seconds = ( intval( $minutesSplit[0] ) + intval( $minutesSplit[1] ) / 10 ) * 60; + + $precision = 1 / 3600; + + $secondsSplit = explode( '.', $seconds ); + + if( isset( $secondsSplit[1] ) ) { + $precision *= pow( 10, -1 * strlen( $secondsSplit[1] ) ); + } + } + + return $precision; + } + + + /** * Returns whether the coordinate is in Decimal Minute representation. * * @since 0.1 diff --git a/ValueParsers/includes/parsers/DmsCoordinateParser.php b/ValueParsers/includes/parsers/DmsCoordinateParser.php index c49c600..c4f5075 100644 --- a/ValueParsers/includes/parsers/DmsCoordinateParser.php +++ b/ValueParsers/includes/parsers/DmsCoordinateParser.php @@ -30,6 +30,7 @@ * * @licence GNU GPL v2+ * @author Jeroen De Dauw < [email protected] > + * @author H. Snater < [email protected] > */ class DmsCoordinateParser extends StringValueParser { @@ -105,17 +106,25 @@ $latitude = $this->getParsedCoordinate( $latitude ); $longitude = $this->getParsedCoordinate( $longitude ); - return new GeoCoordinateValue( $latitude, $longitude ); + $precision = min( $latitude['precision'], $longitude['precision'] ); + + return new GeoCoordinateValue( + $latitude['coordinate'], + $longitude['coordinate'], + null, + $precision + ); } /** - * Parsers a single coordinate (either latitude or longitude) and returns it as a float. + * Parses a coordinate segment (either latitude or longitude) and returns it as a float along + * with the coordinate precision detected. * * @since 0.1 * * @param string $coordinate * - * @return float + * @return array */ protected function getParsedCoordinate( $coordinate ) { $coordinate = $this->resolveDirection( $coordinate ); @@ -201,13 +210,14 @@ } /** - * Takes a set of coordinates in DMS representation, and returns them in float representation. + * Takes a coordinate segment in DMS representation, and returns it in float representation + * along with the coordinate precision detected. * * @since 0.1 * * @param string $coordinate * - * @return float + * @return array */ protected function parseDMSCoordinate( $coordinate ) { $isNegative = $coordinate{0} == '-'; @@ -246,7 +256,35 @@ $coordinate *= -1; } - return (float)$coordinate; + return array( + 'coordinate' => ( float )$coordinate, + 'precision' => $this->detectPrecision( $seconds ), + ); + } + + /** + * Detects the precision of given seconds. + * + * @since 0.1 + * + * @param int|float $seconds + * + * @return float + */ + protected function detectPrecision( $seconds ) { + $precision = 1 / 3600; + + if( $seconds === false ) { + return $precision; + } + + $secondsSplit = explode( '.', $seconds ); + + if( isset( $secondsSplit[1] ) ) { + $precision *= pow( 10, -1 * strlen( $secondsSplit[1] ) ); + } + + return $precision; } /** diff --git a/ValueParsers/includes/parsers/FloatCoordinateParser.php b/ValueParsers/includes/parsers/FloatCoordinateParser.php index cae0950..74d37b2 100644 --- a/ValueParsers/includes/parsers/FloatCoordinateParser.php +++ b/ValueParsers/includes/parsers/FloatCoordinateParser.php @@ -28,6 +28,7 @@ * * @licence GNU GPL v2+ * @author Jeroen De Dauw < [email protected] > + * @author H. Snater < [email protected] > */ class FloatCoordinateParser extends StringValueParser { @@ -91,22 +92,35 @@ $latitude = $this->getParsedCoordinate( $latitude ); $longitude = $this->getParsedCoordinate( $longitude ); - $coordinate = new GeoCoordinateValue( $latitude, $longitude ); + $precision = min( $latitude['precision'], $longitude['precision'] ); + + $coordinate = new GeoCoordinateValue( + $latitude['coordinate'], + $longitude['coordinate'], + null, + $precision + ); return $coordinate; } /** - * Parsers a single coordinate (either latitude or longitude) and returns it as a float. + * Parsers a single coordinate (either latitude or longitude) and returns it as a float along + * with the coordinate precision detected. * * @since 0.1 * * @param string $coordinate * - * @return float + * @return array */ protected function getParsedCoordinate( $coordinate ) { - return (float)$this->resolveDirection( $coordinate ); + $coordinate = ( float )$this->resolveDirection( $coordinate ); + + return array( + 'coordinate' => $coordinate, + 'precision' => $this->detectPrecision( $coordinate ) + ); } /** @@ -142,6 +156,27 @@ } /** + * Detects a number's precision. + * + * @since 0.1 + * + * @param int|float $number + * + * @return int|float + */ + protected function detectPrecision( $number ) { + $split = explode( '.', $number ); + + $precision = 1; + + if( isset( $split[1] ) ) { + $precision = pow( 10, -1 * strlen( $split[1] ) ); + } + + return $precision; + } + + /** * Returns a string with whitespace, control characters and characters with ASCII values above 126 removed. * * @since 0.1 diff --git a/ValueParsers/tests/includes/parsers/DdCoordinateParserTest.php b/ValueParsers/tests/includes/parsers/DdCoordinateParserTest.php index ed7659d..9198663 100644 --- a/ValueParsers/tests/includes/parsers/DdCoordinateParserTest.php +++ b/ValueParsers/tests/includes/parsers/DdCoordinateParserTest.php @@ -50,16 +50,16 @@ // TODO: test with different parser options $valid = array( - '55.7557860° N, 37.6176330° W' => array( 55.7557860, -37.6176330 ), - '55.7557860°, -37.6176330°' => array( 55.7557860, -37.6176330 ), - '55° S, 37.6176330 ° W' => array( -55, -37.6176330 ), - '-55°, -37.6176330 °' => array( -55, -37.6176330 ), - '5.5°S,37°W ' => array( -5.5, -37 ), - '-5.5°,-37° ' => array( -5.5, -37 ), + '55.7557860° N, 37.6176330° W' => array( 55.7557860, -37.6176330, 0.000001 ), + '55.7557860°, -37.6176330°' => array( 55.7557860, -37.6176330, 0.000001 ), + '55° S, 37.6176330 ° W' => array( -55, -37.6176330, 0.000001 ), + '-55°, -37.6176330 °' => array( -55, -37.6176330, 0.000001 ), + '5.5°S,37°W ' => array( -5.5, -37, 0.1 ), + '-5.5°,-37° ' => array( -5.5, -37, 0.1 ), ); foreach ( $valid as $value => $expected ) { - $expected = new GeoCoordinateValue( $expected[0], $expected[1] ); + $expected = new GeoCoordinateValue( $expected[0], $expected[1], null, $expected[2] ); $argLists[] = array( (string)$value, $expected ); } diff --git a/ValueParsers/tests/includes/parsers/DmCoordinateParserTest.php b/ValueParsers/tests/includes/parsers/DmCoordinateParserTest.php index fcd71e8..21e5b89 100644 --- a/ValueParsers/tests/includes/parsers/DmCoordinateParserTest.php +++ b/ValueParsers/tests/includes/parsers/DmCoordinateParserTest.php @@ -50,15 +50,15 @@ // TODO: test with different parser options $valid = array( - "55° 0', 37° 0'" => array( 55, 37 ), - "55° 30′, 37° 30′" => array( 55.5, 37.5 ), - "0° 0', 0° 0'" => array( 0, 0 ), - "-55° 30', -37° 30'" => array( -55.5, -37.5 ), - "0° 0.3' S, 0° 0.3' W" => array( -0.005, -0.005 ), + "55° 0', 37° 0'" => array( 55, 37, 1 / 60 ), + "55° 30′, 37° 30′" => array( 55.5, 37.5, 1 / 60 ), + "0° 0', 0° 0'" => array( 0, 0, 1 / 60 ), + "-55° 30', -37° 30'" => array( -55.5, -37.5, 1 / 60 ), + "0° 0.3' S, 0° 0.3' W" => array( -0.005, -0.005, 1 / 3600 ), ); foreach ( $valid as $value => $expected ) { - $expected = new GeoCoordinateValue( $expected[0], $expected[1] ); + $expected = new GeoCoordinateValue( $expected[0], $expected[1], null, $expected[2] ); $argLists[] = array( (string)$value, $expected ); } diff --git a/ValueParsers/tests/includes/parsers/DmsCoordinateParserTest.php b/ValueParsers/tests/includes/parsers/DmsCoordinateParserTest.php index 4839083..d2c9aba 100644 --- a/ValueParsers/tests/includes/parsers/DmsCoordinateParserTest.php +++ b/ValueParsers/tests/includes/parsers/DmsCoordinateParserTest.php @@ -51,20 +51,20 @@ $valid = array( // DMS - '55° 45\' 20.8296", 37° 37\' 3.4788"' => array( 55.755786, 37.617633 ), - '55° 45\' 20.8296", -37° 37\' 3.4788"' => array( 55.755786, -37.617633 ), - '-55° 45\' 20.8296", -37° 37\' 3.4788"' => array( -55.755786, -37.617633 ), - '-55° 45\' 20.8296", 37° 37\' 3.4788"' => array( -55.755786, 37.617633 ), - '55° 0\' 0", 37° 0\' 0"' => array( 55, 37 ), - '55° 30\' 0", 37° 30\' 0"' => array( 55.5, 37.5 ), - '55° 0′ 18″, 37° 0′ 18″' => array( 55.005, 37.005 ), - '0° 0\' 0", 0° 0\' 0"' => array( 0, 0 ), - '0° 0\' 18" N, 0° 0\' 18" E' => array( 0.005, 0.005 ), - ' 0° 0\' 18" S , 0° 0\' 18" W ' => array( -0.005, -0.005 ), + '55° 45\' 20.8296", 37° 37\' 3.4788"' => array( 55.755786, 37.617633, 1 / 3600 * 0.0001 ), + '55° 45\' 20.8296", -37° 37\' 3.4788"' => array( 55.755786, -37.617633, 1 / 3600 * 0.0001 ), + '-55° 45\' 20.8296", -37° 37\' 3.4788"' => array( -55.755786, -37.617633, 1 / 3600 * 0.0001 ), + '-55° 45\' 20.8296", 37° 37\' 3.4788"' => array( -55.755786, 37.617633, 1 / 3600 * 0.0001 ), + '55° 0\' 0", 37° 0\' 0"' => array( 55, 37, 1 / 3600 ), + '55° 30\' 0", 37° 30\' 0"' => array( 55.5, 37.5, 1 / 3600 ), + '55° 0′ 18″, 37° 0′ 18″' => array( 55.005, 37.005, 1 / 3600 ), + '0° 0\' 0", 0° 0\' 0"' => array( 0, 0, 1 / 3600 ), + '0° 0\' 18" N, 0° 0\' 18" E' => array( 0.005, 0.005, 1 / 3600 ), + ' 0° 0\' 18" S , 0° 0\' 18" W ' => array( -0.005, -0.005, 1 / 3600 ), ); foreach ( $valid as $value => $expected ) { - $expected = new GeoCoordinateValue( $expected[0], $expected[1] ); + $expected = new GeoCoordinateValue( $expected[0], $expected[1], null, $expected[2] ); $argLists[] = array( (string)$value, $expected ); } diff --git a/ValueParsers/tests/includes/parsers/FloatCoordinateParserTest.php b/ValueParsers/tests/includes/parsers/FloatCoordinateParserTest.php index c1676c8..83c124e 100644 --- a/ValueParsers/tests/includes/parsers/FloatCoordinateParserTest.php +++ b/ValueParsers/tests/includes/parsers/FloatCoordinateParserTest.php @@ -50,17 +50,17 @@ // TODO: test with different parser options $valid = array( - '55.7557860 N, 37.6176330 W' => array( 55.7557860, -37.6176330 ), - '55.7557860, -37.6176330' => array( 55.7557860, -37.6176330 ), - '55 S, 37.6176330 W' => array( -55, -37.6176330 ), - '-55, -37.6176330' => array( -55, -37.6176330 ), - '5.5S,37W ' => array( -5.5, -37 ), - '-5.5,-37 ' => array( -5.5, -37 ), - '4,2' => array( 4, 2 ), + '55.7557860 N, 37.6176330 W' => array( 55.7557860, -37.6176330, 0.000001 ), + '55.7557860, -37.6176330' => array( 55.7557860, -37.6176330, 0.000001 ), + '55 S, 37.6176330 W' => array( -55, -37.6176330, 0.000001 ), + '-55, -37.6176330' => array( -55, -37.6176330, 0.000001 ), + '5.5S,37W ' => array( -5.5, -37, 0.1 ), + '-5.5,-37 ' => array( -5.5, -37, 0.1 ), + '4,2' => array( 4, 2, 1 ), ); foreach ( $valid as $value => $expected ) { - $expected = new GeoCoordinateValue( $expected[0], $expected[1] ); + $expected = new GeoCoordinateValue( $expected[0], $expected[1], null, $expected[2] ); $argLists[] = array( (string)$value, $expected ); } diff --git a/ValueParsers/tests/includes/parsers/GeoCoordinateParserTest.php b/ValueParsers/tests/includes/parsers/GeoCoordinateParserTest.php index 748726b..ebac06b 100644 --- a/ValueParsers/tests/includes/parsers/GeoCoordinateParserTest.php +++ b/ValueParsers/tests/includes/parsers/GeoCoordinateParserTest.php @@ -51,44 +51,44 @@ $valid = array( // Float - '55.7557860 N, 37.6176330 W' => array( 55.7557860, -37.6176330 ), - '55.7557860, -37.6176330' => array( 55.7557860, -37.6176330 ), - '55 S, 37.6176330 W' => array( -55, -37.6176330 ), - '-55, -37.6176330' => array( -55, -37.6176330 ), - '5.5S,37W ' => array( -5.5, -37 ), - '-5.5,-37 ' => array( -5.5, -37 ), - '4,2' => array( 4, 2 ), + '55.7557860 N, 37.6176330 W' => array( 55.7557860, -37.6176330, 0.000001 ), + '55.7557860, -37.6176330' => array( 55.7557860, -37.6176330, 0.000001 ), + '55 S, 37.6176330 W' => array( -55, -37.6176330, 0.000001 ), + '-55, -37.6176330' => array( -55, -37.6176330, 0.000001 ), + '5.5S,37W ' => array( -5.5, -37, 0.1 ), + '-5.5,-37 ' => array( -5.5, -37, 0.1 ), + '4,2' => array( 4, 2, 1 ), // DD - '55.7557860° N, 37.6176330° W' => array( 55.7557860, -37.6176330 ), - '55.7557860°, -37.6176330°' => array( 55.7557860, -37.6176330 ), - '55° S, 37.6176330 ° W' => array( -55, -37.6176330 ), - '-55°, -37.6176330 °' => array( -55, -37.6176330 ), - '5.5°S,37°W ' => array( -5.5, -37 ), - '-5.5°,-37° ' => array( -5.5, -37 ), + '55.7557860° N, 37.6176330° W' => array( 55.7557860, -37.6176330, 0.000001 ), + '55.7557860°, -37.6176330°' => array( 55.7557860, -37.6176330, 0.000001 ), + '55° S, 37.6176330 ° W' => array( -55, -37.6176330, 0.000001 ), + '-55°, -37.6176330 °' => array( -55, -37.6176330, 0.000001 ), + '5.5°S,37°W ' => array( -5.5, -37, 0.1 ), + '-5.5°,-37° ' => array( -5.5, -37, 0.1 ), // DMS - '55° 45\' 20.8296", 37° 37\' 3.4788"' => array( 55.755786, 37.617633 ), - '55° 45\' 20.8296", -37° 37\' 3.4788"' => array( 55.755786, -37.617633 ), - '-55° 45\' 20.8296", -37° 37\' 3.4788"' => array( -55.755786, -37.617633 ), - '-55° 45\' 20.8296", 37° 37\' 3.4788"' => array( -55.755786, 37.617633 ), - '55° 0\' 0", 37° 0\' 0"' => array( 55, 37 ), - '55° 30\' 0", 37° 30\' 0"' => array( 55.5, 37.5 ), - '55° 0\' 18", 37° 0\' 18"' => array( 55.005, 37.005 ), - '0° 0\' 0", 0° 0\' 0"' => array( 0, 0 ), - '0° 0′ 18″ N, 0° 0′ 18″ E' => array( 0.005, 0.005 ), - ' 0° 0\' 18" S , 0° 0\' 18" W ' => array( -0.005, -0.005 ), + '55° 45\' 20.8296", 37° 37\' 3.4788"' => array( 55.755786, 37.617633, 1 / 36000000 ), + '55° 45\' 20.8296", -37° 37\' 3.4788"' => array( 55.755786, -37.617633, 1 / 36000000 ), + '-55° 45\' 20.8296", -37° 37\' 3.4788"' => array( -55.755786, -37.617633, 1 / 36000000 ), + '-55° 45\' 20.8296", 37° 37\' 3.4788"' => array( -55.755786, 37.617633, 1 / 36000000 ), + '55° 0\' 0", 37° 0\' 0"' => array( 55, 37, 1 / 3600 ), + '55° 30\' 0", 37° 30\' 0"' => array( 55.5, 37.5, 1 / 3600 ), + '55° 0\' 18", 37° 0\' 18"' => array( 55.005, 37.005, 1 / 3600 ), + '0° 0\' 0", 0° 0\' 0"' => array( 0, 0, 1 / 3600 ), + '0° 0′ 18″ N, 0° 0′ 18″ E' => array( 0.005, 0.005, 1 / 3600 ), + ' 0° 0\' 18" S , 0° 0\' 18" W ' => array( -0.005, -0.005, 1 / 3600 ), // DM - '55° 0\', 37° 0\'' => array( 55, 37 ), - '55° 30\', 37° 30\'' => array( 55.5, 37.5 ), - '0° 0\', 0° 0\'' => array( 0, 0 ), - '-55° 30′, -37° 30′' => array( -55.5, -37.5 ), - '0° 0.3\' S, 0° 0.3\' W' => array( -0.005, -0.005 ), + '55° 0\', 37° 0\'' => array( 55, 37, 1 / 60 ), + '55° 30\', 37° 30\'' => array( 55.5, 37.5, 1 / 60 ), + '0° 0\', 0° 0\'' => array( 0, 0, 1 / 60 ), + '-55° 30′, -37° 30′' => array( -55.5, -37.5, 1 / 60 ), + '0° 0.3\' S, 0° 0.3\' W' => array( -0.005, -0.005, 1 / 3600 ), ); foreach ( $valid as $value => $expected ) { - $expected = new GeoCoordinateValue( $expected[0], $expected[1] ); + $expected = new GeoCoordinateValue( $expected[0], $expected[1], null, $expected[2] ); $argLists[] = array( (string)$value, $expected ); } -- To view, visit https://gerrit.wikimedia.org/r/67976 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I7297d8b9b8e9f8cf39b44f11b38016f19236c541 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/DataValues Gerrit-Branch: master Gerrit-Owner: Henning Snater <[email protected]> _______________________________________________ MediaWiki-commits mailing list [email protected] https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
