Skip to content

Commit

Permalink
Merge pull request #30 from dshanske/display
Browse files Browse the repository at this point in the history
Display Enhancements and More
  • Loading branch information
dshanske committed Jul 15, 2017
2 parents ed9f2b0 + 0d02c66 commit 633892f
Show file tree
Hide file tree
Showing 14 changed files with 557 additions and 127 deletions.
24 changes: 18 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
# Simple Location #
**Contributors:** dshanske
**Tags:** geolocation, geo, maps, location, indieweb
**Stable tag:** 3.1.0
**Stable tag:** 3.2.0
**Requires at least:** 4.7
**Tested up to:** 4.8
**License:** GPLv2 or later
**License URI:** http://www.gnu.org/licenses/gpl-2.0.html

Adds geographic location support to pages and posts.
Adds geographic location support to WordPress.

## Description ##

Supports adding geo coordinates or textual description to a post, and will be supporting saving a location as a venue for reuse. Offers choice of map displays.
Supports adding geo coordinates or textual description to a post, comment, user, or attachment. Will be supporting saving a
location as a venue for reuse. Offers choice of map displays.

It supports retrieving location using the HTML5 geolocation API. As it stores the GeoData in a
WordPress standard format, Geodata can also be added from other plugins.
Expand All @@ -20,12 +21,12 @@ Offers the opportunity to change the displayed timezone on a per-post basis for

## Other Notes ##

* API Keys are required to use [Google Static Maps](https://developers.google.com/maps/documentation/javascript/get-api-key) or [Mapbox Static Maps](https://www.mapbox.com/help/create-api-access-token/).
* API Keys are required to use [Google Static Maps](https://developers.google.com/maps/documentation/javascript/get-api-key), [Mapbox Static Maps](https://www.mapbox.com/help/create-api-access-token/), or [Bing Maps](https://www.bingmapsportal.com/).
If not provided there will be no map displayed regardless of setting. The appropriate API keys should be entered in Settings>>Media or within the admin interface at /wp-admin/options-media.php.

* You can filter any query or archive by adding `?geo={all|public|text}` to it to show only public posts with location. Adding /geo/all to the homepage or archive pages should also work

* Chrome Users: The button that retrieves the location using the HTML5 geolocation API will not work on Chrome if your website is secure(https). This is a Chrome decision to ensure safe control of personal
* Chrome Users: The button that retrieves the location using the HTML5 geolocation API will not work on Chrome if your website is not secure(https). This is a Chrome decision to ensure safe control of personal
data.

* The Development Version as well as support can be found on [Github](https://github.com/dshanske/simple-location).
Expand All @@ -40,7 +41,7 @@ have the advantage of supporting an archive page of all posts from that location
[WordPress Geodata](http://codex.wordpress.org/Geodata) is an existing standard
used to store geodata about a post, user, comment, or term.

**It consists of four fields:** latitude, longitude, public, and address.
**It consists of four fields:** latitude, longitude, public, and address. The plugin also saves zoom which is for the purpose of map display.

## Upgrade Notice ##

Expand All @@ -49,6 +50,17 @@ will now be required to show maps for services that require API keys.

## Changelog ##

### Version 3.2.0 ###
* Allow passing of coordinates directly in constructor for map provider
* Switch to argument array instead of individual properties for most display and data functions
* Support per post zoom settings
* Set initial map zoom based on geolocation accuracy
* Quick and dirty Bing Maps support
* Set location metadata for attachments if in EXIF data
* Add location metabox to attachments
* Add arguments for marking up location
* Add GEORSS support from defunct project

### Version 3.1.0 ###
* New release with more functionality coming soon
* `get_geodata` function now supports WP_Post, WP_Comment, and WP_Term objects
Expand Down
177 changes: 175 additions & 2 deletions includes/class-geo-data.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,128 @@ public static function init() {
add_filter( 'query_vars', array( 'WP_Geo_Data', 'query_var' ) );
add_action( 'pre_get_posts', array( 'WP_Geo_Data', 'pre_get_posts' ) );
add_action( 'save_post', array( 'WP_Geo_Data', 'public_post' ), 99, 2 );

// Grab geo data from EXIF, if it's available
add_action( 'wp_read_image_metadata', array( 'WP_Geo_Data', 'exif_data' ), 10, 3 );
add_action( 'wp_update_attachment_metadata', array( 'WP_Geo_Data', 'attachment' ), 10, 2 );

self::rewrite();

add_action( 'rss2_ns', array( 'WP_Geo_Data', 'georss_namespace' ) );
add_action( 'atom_ns', array( 'WP_Geo_Data', 'georss_namespace' ) );
add_action( 'rdf_ns', array( 'WP_Geo_Data', 'georss_namespace' ) );

add_action( 'rss_item', array( 'WP_Geo_Data', 'georss_item' ) );
add_action( 'rss2_item', array( 'WP_Geo_Data', 'georss_item' ) );
add_action( 'atom_entry', array( 'WP_Geo_Data', 'georss_item' ) );
add_action( 'rdf_item', array( 'WP_Geo_Data', 'georss_item' ) );
}

public static function georss_namespace() {
echo 'xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" ';
}

public static function georss_item() {
$geo = self::get_geodata();
if ( ! $geo ) {
return;
}

if ( empty( $geo['public'] ) || '0' === $geo['public'] ) {
return;
}

$geo = array_map( 'esc_html', $geo );
$geo = array_map( 'ent2ncr', $geo );

echo "\t<georss:point>{$geo['latitude']} {$geo['longitude']}</georss:point>\n";
echo "\t\t<geo:lat>{$geo['latitude']}</geo:lat>\n";
echo "\t\t<geo:long>{$geo['longitude']}</geo:long>";
}

public static function attachment( $meta, $post_id ) {
$current_user = wp_get_current_user();
if ( isset( $meta['image_meta'] ) && isset( $meta['image_meta']['latitude'] ) && isset( $meta['image_meta']['longitude'] ) ) {
update_post_meta( $post_id, 'geo_latitude', $meta['image_meta']['latitude'] );
update_post_meta( $post_id, 'geo_longitude', $meta['image_meta']['longitude'] );
}
return $meta;
}

public static function DECtoDMS( $latitude, $longitude ) {
$latitudeDirection = $latitude < 0 ? 'S': 'N';
$longitudeDirection = $longitude < 0 ? 'W': 'E';

$latitudeNotation = $latitude < 0 ? '-': '';
$longitudeNotation = $longitude < 0 ? '-': '';

$latitudeInDegrees = floor( abs( $latitude ) );
$longitudeInDegrees = floor( abs( $longitude ) );

$latitudeDecimal = abs( $latitude ) -$latitudeInDegrees;
$longitudeDecimal = abs( $longitude ) -$longitudeInDegrees;

$_precision = 3;
$latitudeMinutes = round( $latitudeDecimal * 60,$_precision );
$longitudeMinutes = round( $longitudeDecimal * 60,$_precision );

return sprintf('%s%s° %s %s %s%s° %s %s',
$latitudeNotation,
$latitudeInDegrees,
$latitudeMinutes,
$latitudeDirection,
$longitudeNotation,
$longitudeInDegrees,
$longitudeMinutes,
$longitudeDirection
);

}

public static function gps($coordinate, $hemisphere) {
for ( $i = 0; $i < 3; $i++ ) {
$part = explode( '/', $coordinate[$i] );
if ( count( $part ) == 1 ) {
$coordinate[$i] = $part[0];
} else if ( count( $part ) == 2 ) {
$coordinate[$i] = floatval( $part[0] ) / floatval( $part[1] );
} else {
$coordinate[$i] = 0;
}
}
list($degrees, $minutes, $seconds) = $coordinate;
$sign = ($hemisphere == 'W' || $hemisphere == 'S') ? -1 : 1;
return $sign * ($degrees + $minutes / 60 + $seconds / 3600);
}

public static function exif_data( $meta, $file, $file_type ) {
if ( in_array( $file_type, apply_filters( 'wp_read_image_metadata_types', array( IMAGETYPE_JPEG, IMAGETYPE_TIFF_II, IMAGETYPE_TIFF_MM ) ) ) ) {
// If there is invalid EXIF data this will emit a warning, even
// when using the @ operator. A correct approach would be to
// validate the EXIF data before attempting to use it. For now,
// just avoiding spewing warnings.
$old_level = error_reporting( E_ERROR );
$exif = exif_read_data( $file );
error_reporting( $old_level );

if ( ! empty( $exif['GPSLatitude'] ) ) {
$meta['latitude'] = self::gps( $exif['GPSLatitude'], $exif['GPSLatitudeRef'] );
}

if ( ! empty( $exif['GPSLongitude'] ) ) {
$meta['longitude'] = self::gps( $exif['GPSLongitude'], $exif['GPSLongitudeRef'] );
}
}
return $meta;
}

// Set Posts Added by Means other than the Post UI to the system default if not set
public static function public_post( $post_id, $post ) {
$lat = get_post_meta( $post_id, 'geo_latitude' );
$add = get_post_meta( $post_id, 'geo_address' );
if ( ! $lat || ! $add ) {
return;
}
$public = get_post_meta( $post_id, 'geo_public' );
if ( ! $public ) {
add_post_meta( $post_id, 'geo_public', get_option( 'geo_public' ) );
Expand Down Expand Up @@ -75,6 +192,46 @@ public static function clean_coordinate( $coordinate ) {
return $matches[0];
}

public static function set_geodata( $object = null, $geodata ) {
if ( ! is_array( $geodata ) ) {
return false;
}
$geodata = wp_array_slice_assoc( $geodata, 'latitude', 'longitude', 'address', 'map_zoom' );
if ( isset( $geodata['map_zoom'] ) ) {
$geodata['zoom'] = $geodata['map_zoom'];
unset( $geodata['map_zoom'] );
}

if ( ! $object ) {
$object = get_post();
}
// If numeric assume post_ID
if ( is_numeric( $object ) ) {
$object = get_post( $object );
}
if ( $object instanceof WP_Post ) {
foreach ( $geodata as $key => $value ) {
update_post_meta( $object->ID, 'geo_' . $key, $value );
}
}

if ( $object instanceof WP_Comment ) {
foreach ( $geodata as $key => $value ) {
update_comment_meta( $object->comment_ID, 'geo_' . $key, $value );
}
}
if ( $object instanceof WP_Term ) {
foreach ( $geodata as $key => $value ) {
update_term_meta( $object->term_id, 'geo_' . $key, $value );
}
}
if ( $object instanceof WP_User ) {
foreach ( $geodata as $key => $value ) {
update_user_meta( $object->ID, 'geo_' . $key, $value );
}
}
}

public static function get_geodata( $object = null ) {
$geodata = array();
if ( ! $object ) {
Expand All @@ -88,6 +245,7 @@ public static function get_geodata( $object = null ) {
$geodata['longitude'] = get_post_meta( $object->ID, 'geo_longitude', true );
$geodata['latitude'] = get_post_meta( $object->ID, 'geo_latitude', true );
$geodata['address'] = get_post_meta( $object->ID, 'geo_address', true );
$geodata['map_zoom'] = get_post_meta( $object->ID, 'geo_zoom', true );
if ( empty( $geodata['longitude'] ) && empty( $geodata['address'] ) ) {
return null;
}
Expand All @@ -103,6 +261,7 @@ public static function get_geodata( $object = null ) {
$geodata['longitude'] = get_comment_meta( $object->comment_ID, 'geo_longitude', true );
$geodata['latitude'] = get_comment_meta( $object->comment_ID, 'geo_latitude', true );
$geodata['address'] = get_comment_meta( $object->comment_ID, 'geo_address', true );
$geodata['map_zoom'] = get_comment_meta( $object->comment_ID, 'geo_zoom', true );
if ( empty( $geodata['longitude'] ) && empty( $geodata['address'] ) ) {
return null;
}
Expand All @@ -113,6 +272,7 @@ public static function get_geodata( $object = null ) {
$geodata['longitude'] = get_term_meta( $object->term_id, 'geo_longitude', true );
$geodata['latitude'] = get_term_meta( $object->term_id, 'geo_latitude', true );
$geodata['address'] = get_term_meta( $object->term_id, 'geo_address', true );
$geodata['map_zoom'] = get_term_meta( $object->term_id, 'geo_zoom', true );
if ( empty( $geodata['longitude'] ) && empty( $geodata['address'] ) ) {
return null;
}
Expand All @@ -123,19 +283,20 @@ public static function get_geodata( $object = null ) {
$geodata['longitude'] = get_user_meta( $object->ID, 'geo_longitude', true );
$geodata['latitude'] = get_user_meta( $object->ID, 'geo_latitude', true );
$geodata['address'] = get_user_meta( $object->ID, 'geo_address', true );
$geodata['map_zoom'] = get_user_meta( $object->ID, 'geo_zoom', true );
if ( empty( $geodata['longitude'] ) && empty( $geodata['address'] ) ) {
return null;
}
$geodata['public'] = get_user_meta( $object->ID, 'geo_public', true );
$geodata['user_ID'] = $object->ID;
}
$geodata = array_filter( $geodata );

if ( empty( $geodata['address'] ) ) {
if ( empty( $geodata['longitude'] ) ) {
return null;
}
$map = Loc_Config::default_reverse_provider();
$map->set( $geodata['latitude'], $geodata['longitude'] );
$map = Loc_Config::default_reverse_provider( $geodata );
$adr = $map->reverse_lookup();
if ( array_key_exists( 'display-name', $adr ) ) {
$geodata['address'] = trim( $adr['display-name'] );
Expand Down Expand Up @@ -200,6 +361,18 @@ public static function register_meta() {
register_meta( 'user', 'geo_timezone', $args );
register_meta( 'term', 'geo_timezone', $args );

$args = array(
// 'sanitize_callback' => '',
'type' => 'integer',
'description' => 'Geodata Zoom for Map Display',
'single' => true,
'show_in_rest' => false,
);
register_meta( 'post', 'geo_zoom', $args );
register_meta( 'comment', 'geo_zoom', $args );
register_meta( 'user', 'geo_zoom', $args );
register_meta( 'term', 'geo_zoom', $args );

$args = array(
// 'sanitize_callback' => '',
'type' => 'integer',
Expand Down
48 changes: 48 additions & 0 deletions includes/class-geo-provider-bing.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php
// Bing Map Provider
class Geo_Provider_Bing extends Geo_Provider {


public function __construct( $args = array() ) {
if ( ! isset( $args['api'] ) ) {
$args['api'] = get_option( 'sloc_bing_api' );
}
parent::__construct( $args );
}

public function reverse_lookup( ) {
$response = wp_remote_get( 'http://dev.virtualearth.net/REST/v1/Locations/' . $this->latitude . ',' . $this->longitude . '&key=' . $this->api );
$json = json_decode( $response['body'], true );
//$address = $json['results'][0]['address_components'];
$addr = array(
// 'name' => $json['results'][0]['formatted_address'],
'latitude' => $this->latitude,
'longitude' => $this->longitude,
'raw' => $json,
);
$addr = array_filter( $addr );
// $addr['display-name'] = $this->display_name( $addr );
$tz = $this->timezone( $this->latitude, $this->longitude );
$addr = array_merge( $addr, $tz );
return $addr;
}

// Return code for map
public function get_the_static_map( ) {
$map = 'http://dev.virtualearth.net/REST/v1/Imagery/Map/CanvasLight/' . $this->latitude . ',' . $this->longitude . '/' . $this->map_zoom . '?mapSize=' . $this->width . ',' . $this->height . '&key=' . $this->api;
return $map;
}

public function get_the_map_url() {
return 'http://bing.com/maps/default.aspx?cp=' . $this->latitude . ',' . $this->longitude . '&lvl=' . $this->map_zoom;
}

// Return code for map
public function get_the_map( $static = true) {
$map = $this->get_the_static_map( );
$link = $this->get_the_map_url( );
$c = '<a href="' . $link . '"><img src="' . $map . '" /></a>';
return $c;
}

}
2 changes: 1 addition & 1 deletion includes/class-geo-provider-google.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public function reverse_lookup( ) {

// Return code for map
public function get_the_static_map( ) {
$map = 'https://maps.googleapis.com/maps/api/staticmap?markers=color:red%7Clabel:P%7C' . $this->latitude . ',' . $this->longitude . '&size=' . $this->height . 'x' . $this->width . '&language=' . get_bloginfo( 'language' ) . '&key=' . $this->api;
$map = 'https://maps.googleapis.com/maps/api/staticmap?markers=color:red%7Clabel:P%7C' . $this->latitude . ',' . $this->longitude . '&size=' . $this->width . 'x' . $this->height . '&language=' . get_bloginfo( 'language' ) . '&key=' . $this->api;
return $map;
}

Expand Down
6 changes: 2 additions & 4 deletions includes/class-geo-provider-osm.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ public function __construct( $args = array() ) {
if ( ! isset( $args['api'] ) ) {
$args['api'] = get_option( 'sloc_mapbox_api' );
}
if ( ! isset( $args['map_zoom'] ) ) {
$args['map_zoom'] = 18;
}

parent::__construct( $args );
}

Expand Down Expand Up @@ -65,7 +63,7 @@ public function get_the_map( $static = true ) {
}

public function get_the_static_map( ) {
$map = 'https://api.mapbox.com/styles/v1/mapbox/streets-v8/static/' . $this->longitude . ',' . $this->latitude. ',' . $this->map_zoom . ',0,0/' . $this->height . 'x' . $this->width . '?access_token=' . $this->api;
$map = 'https://api.mapbox.com/styles/v1/mapbox/streets-v8/static/' . $this->longitude . ',' . $this->latitude. ',' . $this->map_zoom . ',0,0/' . $this->width . 'x' . $this->height . '?access_token=' . $this->api;
return $map;

}
Expand Down
Loading

0 comments on commit 633892f

Please sign in to comment.