Making WordPress.org

Changeset 5101


Ignore:
Timestamp:
03/07/2017 01:28:40 AM (9 years ago)
Author:
iandunn
Message:

Events API: Extract country IDs from multi-word inputs to improve matching

This enables successfully matching locations for country codes in inputs like "GB" and "London GB"; and also matching country names of varying length, regardless of the city length, in inputs like "Vancouver Canada", "Santiago De Los Caballeros, Dominican Republic", and "Kaga-Bandoro, Central African Republic".

Location:
sites/trunk/api.wordpress.org/public_html/events/1.0
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/api.wordpress.org/public_html/events/1.0/index.php

    r5100 r5101  
    271271 * Guess the location based on a country identifier inside the given input
    272272 *
     273 * This isn't perfect because some of the country names in the database are in a format that regular
     274 * people wouldn't type -- e.g., "Venezuela, Bolvarian Republic Of" -- but this will still match a
     275 * majority of them.
     276 *
     277 * Currently, this only works with English names because that's the only data we have.
     278 *
    273279 * @param string $location_name
    274280 *
     
    276282 */
    277283function guess_location_from_country( $location_name ) {
     284        // Check if they entered only the country name, e.g. "Germany" or "New Zealand"
     285        $country_code = get_country_code_from_name( $location_name );
     286        $location_word_count = str_word_count( $location_name );
     287        $location_name_parts = explode( ' ', $location_name );
     288
     289        // Check if they entered only the country code, e.g., "GB"
     290        if ( ! $country_code ) {
     291                $valid_country_codes = get_valid_country_codes();
     292
     293                if ( in_array( $location_name, $valid_country_codes, true ) ) {
     294                        $country_code = $location_name;
     295                }
     296        }
     297
    278298        /*
    279          * Check if they entered only the country name, e.g. "Germany" or "New Zealand"
    280          *
    281          * This isn't perfect because some of the country names in the database are in a format that regular
    282          * people wouldn't type -- e.g., "Venezuela, Bolvarian Republic Of" -- but this will still match a
    283          * majority of them.
    284          *
    285          * Currently, this only works with English names because that's the only data we have.
     299         * Multi-word queries may contain cities, regions, and countries, so try to extract just the country
    286300         */
    287         $location_country_code = get_country_code_from_name( $location_name );
    288 
    289         return $location_country_code;
     301        if ( ! $country_code && $location_word_count >= 2 ) {
     302                // Catch input like "Vancouver Canada"
     303                $country_id   = $location_name_parts[ $location_word_count - 1 ];
     304                $country_code = get_country_code_from_name( $country_id );
     305
     306                // Catch input like "London GB"
     307                if ( ! $country_code ) {
     308                        if ( in_array( $country_id, $valid_country_codes, true ) ) {
     309                                $country_code = $country_id;
     310                        }
     311                }
     312        }
     313
     314        if ( ! $country_code && $location_word_count >= 3 ) {
     315                // Catch input like "Santiago De Los Caballeros, Dominican Republic"
     316                $country_name = sprintf(
     317                        '%s %s',
     318                        $location_name_parts[ $location_word_count - 2 ],
     319                        $location_name_parts[ $location_word_count - 1 ]
     320                );
     321                $country_code = get_country_code_from_name( $country_name );
     322        }
     323
     324        if ( ! $country_code && $location_word_count >= 4 ) {
     325                // Catch input like "Kaga-Bandoro, Central African Republic"
     326                $country_name = sprintf(
     327                        '%s %s %s',
     328                        $location_name_parts[ $location_word_count - 3 ],
     329                        $location_name_parts[ $location_word_count - 2 ],
     330                        $location_name_parts[ $location_word_count - 1 ]
     331                );
     332                $country_code = get_country_code_from_name( $country_name );
     333        }
     334
     335        return $country_code;
     336}
     337
     338/**
     339 * Get a list of valid country codes
     340 *
     341 * @return array
     342 */
     343function get_valid_country_codes() {
     344        global $wpdb;
     345
     346        return $wpdb->get_col( "SELECT DISTINCT country FROM geoname" );
    290347}
    291348
  • sites/trunk/api.wordpress.org/public_html/events/1.0/tests/test-index.php

    r5100 r5101  
    427427                /*
    428428                 * A combination of city, region, and country are given, along with the locale and timezone
     429                 *
     430                 * InvalidCity is used in tests that want to bypass the guess_location_from_city() tests and only test the country
    429431                 */
    430432                '1-word-city-region' => array(
     
    456458                ),
    457459
     460                'city-1-word-country' => array(
     461                        'input' => array(
     462                                'location_name' => 'InvalidCity Canada',
     463                                'locale'        => 'en_CA',
     464                                'timezone'      => 'America/Vancouver',
     465                        ),
     466                        'expected' => array(
     467                                'country' => 'CA',
     468                        ),
     469                ),
     470
     471                'city-2-word-country' => array(
     472                        'input' => array(
     473                                'location_name' => 'InvalidCity Dominican Republic',
     474                                'locale'        => 'es_ES',
     475                                'timezone'      => 'America/Santo_Domingo',
     476                        ),
     477                        'expected' => array(
     478                                'country' => 'DO',
     479                        ),
     480                ),
     481
     482                'city-3-word-country' => array(
     483                        'input' => array(
     484                                'location_name' => 'InvalidCity Central African Republic',
     485                                'locale'        => 'fr_FR',
     486                                'timezone'      => 'Africa/Bangui',
     487                        ),
     488                        'expected' => array(
     489                                'country' => 'CF',
     490                        ),
     491                ),
     492
     493                'country-code' => array(
     494                        'input' => array(
     495                                'location_name' => 'GB',
     496                                'locale'        => 'en_GB',
     497                                'timezone'      => 'Europe/London',
     498                        ),
     499                        'expected' => array(
     500                                'country' => 'GB',
     501                        ),
     502                ),
     503
     504                'city-country-code' => array(
     505                        'input' => array(
     506                                'location_name' => 'InvalidCity BI',
     507                                'locale'        => 'fr_FR',
     508                                'timezone'      => 'Africa/Bujumbura',
     509                        ),
     510                        'expected' => array(
     511                                'country' => 'BI',
     512                        ),
     513                ),
     514
    458515
    459516                /*
Note: See TracChangeset for help on using the changeset viewer.