=== WP Geo search ===
Contributors: jhackett1
Donate link: https://github.com/jhackett1/wp-geo-search
Tags: geo, location, nominatim, distance, haversine, maps, mapping
Requires at least: 4.0
Tested up to: 5.8.0
Stable tag: 4
Requires PHP: 7.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Add location-aware geographical search to WP_Query. You can use it to power location-aware apps, such as showing a user results near them.

[Nominatim](https://nominatim.org/)'s service is used for geocoding location searches.

== Description ==

A plugin to add location-aware geographical search to [WP_Query](https://developer.wordpress.org/reference/classes/wp_query/).

You can use it to power location-aware apps, such as showing a user results near them.

## 🔎 Using it in a query

Adding a `geo_query` parameter to WP_Query will add a "distance" column to the returned results, provided they have the right metadata.

You can then display this in your templates.

You can use a location search parameter, which will be [geocoded](#geocoding) or directly provide latitude and longitude values:


`
$query = new WP_Query(array(
    "geo_query" => array(
            "location" => "London"
    )
))

$query = new WP_Query(array(
    "geo_query" => array(
            "latitude" => -52.005,
            "longitude" => 0.005,
    )
))
`

Optionally, you can then filter by search radius.

By default, distances are given in miles. You can provide `"units" => "km"` if you need kilometres.

`
$query = new WP_Query(array(
    "geo_query" => array(
            "latitude" => -52.005,
            "longitude" => 0.005,
            "radius" => 10
    )
))
`

Or order by nearness:

`
$query = new WP_Query(array(
    "geo_query" => array(
            "latitude" => -52.005,
            "longitude" => 0.005
    ),
    "orderby" => "geo"
))
`

### Displaying distance in templates

In a `WP_Query` loop that includes a `geo_query`, you can use two extra functions to show distance away:

- `jhgs_get_the_distance(object $post)` - which returns a rounded integer for the distance away, similar to `get_the_title()`
- `jhgs_the_distance(string $less_than_one, string $one, string $more_than_one)` - which displays an approximate human-readable string, similar to `the_title()`

`jhgs_the_distance` will show one of three messages depending on whether the rounded distance is less than one, one, or greater than one. By default these are:

- "Less than a mile away"
- "About a mile away"
- "About %s miles away"

If you need to use different units or translations, can pass three [printf-formatted](https://www.php.net/manual/en/function.printf.php) strings to `jhgs_the_distance()` to override these messages. Put `%s` where you want the value.

If you need the _exact_, unrounded value, you can use `$post->distance`.

### Geocoding

[Nominatim](https://nominatim.org/)'s service is used for geocoding location searches.

Using it is subject to an [acceptable use policy](https://operations.osmfoundation.org/policies/nominatim/) - if you use case will involve lots of API calls, you should replace it with a paid alternative, like [Google](https://developers.google.com/maps/documentation/geocoding/overview)'s.

## 📍 Populating latitude and longitude data

It looks for two [custom field](https://wordpress.org/support/article/custom-fields/) values with the keys `latitude` and `longitude` on your posts.

It's agnostic about how you supply this data. The simplest thing to do is type it in using WordPress's built-in custom field editor.

You could also hook into the `save_post` action to populate meta whenever you create or change a post, by adding a snippet like this to your theme's `functions.php`:

`
function example_update_latlngs($post){
    $location = get_field("location", $post);
    if(isset($location)){
        update_post_meta($post, "longitude", $location["lng"]);
        update_post_meta($post, "latitude", $location["lat"]);
    }
}

add_action("save_post", "example_update_latlngs", 10, 3);
`

This example assumes you are using an [ACF Google Map](https://www.advancedcustomfields.com/resources/google-map/) field called "location", but the data could come from anywhere, including a custom meta box you code yourself, so long as the post meta keys are right.

### Bulk-updating existing posts

If you have many posts that you need to add longitude and latitude meta to in bulk, you could add something like this to `functions.php`, which will run on [theme activation](https://developer.wordpress.org/reference/hooks/after_switch_theme/):

`
function example_update_all_latlngs(){
    $query = new WP_Query(array(
        "posts_per_page" => -1
    ));
    foreach($query->get_posts() as $post){
        // Function from above
        example_update_latlngs($post);
    }
}

add_action('after_switch_theme', 'example_update_all_latlngs');
`


== Frequently Asked Questions ==

= I've activated it, but I can't see any changes to my website =

This plugin adds extra functionality to `WP_Query` - it's up to you to make use of that functionality in your theme.

== Changelog ==

= 0.1 =
* First release
