diff --git a/readme.txt b/readme.txt
index 54bd778..3ff3fca 100755
--- a/readme.txt
+++ b/readme.txt
@@ -135,7 +135,8 @@ On the WP-Strava settings page you cannot currently remove and add another athle
== Changelog ==
= 2.11.0 =
-Added additional block transformations for "Activity" (from: Paragraph, Classic Shortcode; to: Paragraph)
+Add additional block transformations for "Activity" (from: Paragraph, Classic Shortcode; to: Paragraph)
+Add Mapbox Static Map support https://github.com/cmanon/wp-strava/issues/26
= 2.10.1 =
diff --git a/src/WPStrava.php b/src/WPStrava.php
index 27ce19d..212b100 100644
--- a/src/WPStrava.php
+++ b/src/WPStrava.php
@@ -95,6 +95,7 @@ class WPStrava {
if ( is_admin() ) {
$this->settings->hook();
+ add_action( 'admin_enqueue_scripts', array( $this, 'register_admin_scripts' ) );
} else { // Front-end.
add_action( 'init', array( $this, 'register_shortcodes' ) );
add_action( 'wp_enqueue_scripts', array( $this, 'register_scripts' ) );
@@ -188,6 +189,18 @@ class WPStrava {
return $this->segments;
}
+ /**
+ * Register/enqueue admin javascript.
+ *
+ * @author Justin Foell
+ * @since 2.11
+ */
+ public function register_admin_scripts() {
+ if ( $this->settings->is_settings_page() ) {
+ wp_enqueue_script( 'strava-admin-settings', WPSTRAVA_PLUGIN_URL . 'src/admin-settings.js', array(), WPSTRAVA_PLUGIN_VERSION, true );
+ }
+ }
+
/**
* Register the wp-strava stylesheet.
*/
diff --git a/src/WPStrava/ActivityRenderer.php b/src/WPStrava/ActivityRenderer.php
index 26ecef6..cb0edf3 100644
--- a/src/WPStrava/ActivityRenderer.php
+++ b/src/WPStrava/ActivityRenderer.php
@@ -55,7 +55,7 @@ class WPStrava_ActivityRenderer {
$activity_output .= $activity->get_activity_link(
$activity_details->id,
- WPStrava_StaticMap::get_image_tag( $activity_details, $map_height, $map_width, $atts['markers'], $activity_details->name ),
+ WPStrava_StaticMap::get_map()->get_image_tag( $activity_details, $map_height, $map_width, $atts['markers'], $activity_details->name ),
$activity_details->name
);
diff --git a/src/WPStrava/LatestMap.php b/src/WPStrava/LatestMap.php
index a28815d..e62a4d9 100644
--- a/src/WPStrava/LatestMap.php
+++ b/src/WPStrava/LatestMap.php
@@ -54,7 +54,7 @@ class WPStrava_LatestMap {
// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped -- Image OK.
$strava_activity->get_activity_link(
$activity->id,
- WPStrava_StaticMap::get_image_tag( $activity, null, null, false, $activity->name ),
+ WPStrava_StaticMap::get_map()->get_image_tag( $activity, null, null, false, $activity->name ),
$activity->name
);
// phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped
diff --git a/src/WPStrava/RouteRenderer.php b/src/WPStrava/RouteRenderer.php
index 524e8ff..f507635 100644
--- a/src/WPStrava/RouteRenderer.php
+++ b/src/WPStrava/RouteRenderer.php
@@ -60,7 +60,7 @@ class WPStrava_RouteRenderer {
$route_output .= $route->get_route_link(
$route_details->id,
- WPStrava_StaticMap::get_image_tag( $route_details, $map_height, $map_width, $atts['markers'], $route_details->name ),
+ WPStrava_StaticMap::get_map()->get_image_tag( $route_details, $map_height, $map_width, $atts['markers'], $route_details->name ),
$route_details->name
);
diff --git a/src/WPStrava/SegmentsRenderer.php b/src/WPStrava/SegmentsRenderer.php
index c034611..c7a9631 100644
--- a/src/WPStrava/SegmentsRenderer.php
+++ b/src/WPStrava/SegmentsRenderer.php
@@ -63,7 +63,7 @@ class WPStrava_SegmentsRenderer {
$segments_output .= $segments->get_segments_link(
$segment_details->id,
- WPStrava_StaticMap::get_image_tag( $segment_details, $map_height, $map_width, $atts['markers'], $segment_details->name ),
+ WPStrava_StaticMap::get_map()->get_image_tag( $segment_details, $map_height, $map_width, $atts['markers'], $segment_details->name ),
$segment_details->name
);
diff --git a/src/WPStrava/Settings.php b/src/WPStrava/Settings.php
index aaa50b2..d4b8401 100644
--- a/src/WPStrava/Settings.php
+++ b/src/WPStrava/Settings.php
@@ -80,9 +80,16 @@ class WPStrava_Settings {
}
// Google Maps API.
+ add_settings_section( 'strava_maps', __( 'Maps', 'wp-strava' ), null, 'wp-strava' );
+
+ register_setting( $this->option_page, 'strava_map_type', array( $this, 'sanitize_map_type' ) );
+ add_settings_field( 'strava_map_type', __( 'Map Type', 'wp-strava' ), array( $this, 'print_map_type_input' ), 'wp-strava', 'strava_maps' );
+
register_setting( $this->option_page, 'strava_gmaps_key', array( $this, 'sanitize_gmaps_key' ) );
- add_settings_section( 'strava_gmaps', __( 'Google Maps', 'wp-strava' ), array( $this, 'print_gmaps_instructions' ), 'wp-strava' );
- add_settings_field( 'strava_gmaps_key', __( 'Static Maps Key', 'wp-strava' ), array( $this, 'print_gmaps_key_input' ), 'wp-strava', 'strava_gmaps' );
+ add_settings_field( 'strava_gmaps_key', __( 'Google Static Maps API Key', 'wp-strava' ), array( $this, 'print_gmaps_key_input' ), 'wp-strava', 'strava_maps' );
+
+ register_setting( $this->option_page, 'strava_mapbox_token', array( $this, 'sanitize_mapbox_token' ) );
+ add_settings_field( 'strava_mapbox_token', __( 'Mapbox Public Token', 'wp-strava' ), array( $this, 'print_mapbox_token_input' ), 'wp-strava', 'strava_maps' );
// System of Measurement.
register_setting( $this->option_page, 'strava_som', array( $this, 'sanitize_som' ) );
@@ -160,27 +167,80 @@ class WPStrava_Settings {
}
/**
- * Print the google maps instructions.
+ * Print the map type selection.
*
* @author Justin Foell
- * @since 1.1
+ * @since 2.11
*/
- public function print_gmaps_instructions() {
- $maps_url = 'https://developers.google.com/maps/documentation/static-maps/';
- echo wp_kses_post(
- sprintf(
- __(
- "Steps:
-
- To use Google map images, you must create a Static Maps API Key. Create a free key by going here: %2\$s and clicking Get a Key
- Once you've created your Google Static Maps API Key, enter the key below.
- ",
- 'wp-strava'
- ),
- $maps_url,
- $maps_url
- )
- );
+ public function print_map_type_input() {
+ $gmaps_url = 'https://developers.google.com/maps/documentation/static-maps/';
+ $mapbox_url = 'https://www.mapbox.com/static-maps';
+ $selected = 'mapbox' === $this->map_type ? 'mapbox' : 'gmaps';
+ $gmaps_class = 'gmaps' !== $selected ? 'hidden' : '';
+ $mapbox_class = 'mapbox' !== $selected ? 'hidden' : '';
+
+ ?>
+
+ map_type, 'gmaps' ); ?>>
+ map_type, 'mapbox' ); ?>>
+
+
+
+
+
+ Steps:
+
+ To use Google map images, you must create a Static Maps API Key. Google now requires billing information for overages, but effectively gives you 100k map loads for free each month. Create your Google Static Maps API key by going here: %2\$s
+ Once you've created your Google Static Maps API Key, enter the key below.
+ ",
+ 'wp-strava'
+ ),
+ $gmaps_url,
+ $gmaps_url
+ )
+ );
+ ?>
+
+
+ Steps:
+
+ To use Mapbox map images, create a free Mapbox account here: %2\$s
+ All Mapbox accounts are issued a default public access token, enter the token below.
+ ",
+ 'wp-strava'
+ ),
+ $mapbox_url,
+ $mapbox_url
+ )
+ );
+ ?>
+
+
+
+
+ * @since 2.11
+ */
+ public function sanitize_map_type_input( $map_type ) {
+ if ( in_array( $map_type, array( 'gmaps', 'mapbox' ), true ) ) {
+ return $map_type;
+ }
+ return '';
}
/**
@@ -389,7 +449,7 @@ class WPStrava_Settings {
$infos = $this->info;
foreach ( $infos as $id => $info ) {
- if ( ! in_array( $id, $ids ) ) {
+ if ( ! in_array( $id, $ids ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict -- loose OK.
$update = true;
unset( $infos[ $id ] );
}
@@ -425,6 +485,30 @@ class WPStrava_Settings {
return $key;
}
+ /**
+ * Print the Mapbox token input.
+ *
+ * @author Justin Foell
+ * @since 2.11
+ */
+ public function print_mapbox_token_input() {
+ ?>
+
+
+ * @since 2.11
+ */
+ public function sanitize_mapbox_token( $token ) {
+ return $token;
+ }
+
/**
* Print System of Measure option.
*
diff --git a/src/WPStrava/StaticGMap.php b/src/WPStrava/StaticGMap.php
new file mode 100644
index 0000000..b7f99b8
--- /dev/null
+++ b/src/WPStrava/StaticGMap.php
@@ -0,0 +1,54 @@
+settings->gmaps_key;
+
+ // Short circuit if missing key or activity object doesn't have the data we need.
+ if ( empty( $key ) || empty( $activity->map ) ) {
+ return '';
+ }
+
+ if ( ! $height || ! $width ) {
+ $height = 320;
+ $width = 480;
+ }
+
+ $url = "https://maps.googleapis.com/maps/api/staticmap?maptype=terrain&size={$width}x{$height}&scale=2&sensor=false&key={$key}&path=color:0xFF0000BF|weight:2|enc:";
+ $url_len = strlen( $url );
+
+ $polyline = '';
+ if ( ! empty( $activity->map->polyline ) && ( $url_len + strlen( $activity->map->polyline ) < self::$max_chars ) ) {
+ $polyline = $activity->map->polyline;
+ } elseif ( ! empty( $activity->map->summary_polyline ) ) {
+ $polyline = $activity->map->summary_polyline;
+ } elseif ( ! empty( $activity->map->polyline ) ) {
+ // Need to reduce the polyline b/c it's too big and no summary was provided.
+ $polyline = $this->reduce_polyline( $url_len, $activity->map->polyline );
+ }
+ $url .= $polyline;
+
+ if ( $markers ) {
+ $points = $this->decode_start_finish( $polyline );
+ $markers = '&markers=color:green|' . $points['start'][0] . ',' . $points['start'][1] .
+ '&markers=color:red|' . $points['finish'][0] . ',' . $points['finish'][1];
+ $url .= $markers;
+ }
+
+ $title_attr = $title ? " title='" . esc_attr( $title ) . "'" : '';
+ return " ";
+ }
+}
diff --git a/src/WPStrava/StaticMap.php b/src/WPStrava/StaticMap.php
index 1db9475..d52348c 100644
--- a/src/WPStrava/StaticMap.php
+++ b/src/WPStrava/StaticMap.php
@@ -1,16 +1,12 @@
settings->gmaps_key;
+ abstract public function get_image_tag( $activity, $height = 320, $width = 480, $markers = false, $title = '' );
- // Short circuit if missing key or activity object doesn't have the data we need.
- if ( empty( $key ) || empty( $activity->map ) ) {
- return '';
+ /**
+ * Factory method to get the correct StaticMap class based on options setting.
+ *
+ * @return WPStrava_StaticMap Instance of StaticMap
+ * @author Justin Foell
+ * @since 2.11
+ */
+ public static function get_map() {
+ if ( 'mapbox' === WPStrava::get_instance()->settings->map_type ) {
+ return new WPStrava_StaticMapbox();
}
-
- if ( ! $height || ! $width ) {
- $height = 320;
- $width = 480;
- }
-
- $url = "https://maps.googleapis.com/maps/api/staticmap?maptype=terrain&size={$width}x{$height}&scale=2&sensor=false&key={$key}&path=color:0xFF0000BF|weight:2|enc:";
- $url_len = strlen( $url );
-
- $polyline = '';
- if ( ! empty( $activity->map->polyline ) && ( $url_len + strlen( $activity->map->polyline ) < self::$max_chars ) ) {
- $polyline = $activity->map->polyline;
- } elseif ( ! empty( $activity->map->summary_polyline ) ) {
- $polyline = $activity->map->summary_polyline;
- } elseif ( ! empty( $activity->map->polyline ) ) {
- // Need to reduce the polyline b/c it's too big and no summary was provided.
- $polyline = self::reduce_polyline( $url_len, $activity->map->polyline );
- }
- $url .= $polyline;
-
- if ( $markers ) {
- $points = self::decode_start_finish( $polyline );
- $markers = '&markers=color:green|' . $points['start'][0] . ',' . $points['start'][1] .
- '&markers=color:red|' . $points['finish'][0] . ',' . $points['finish'][1];
- $url .= $markers;
- }
-
- $title_attr = $title ? " title='" . esc_attr( $title ) . "'" : '';
- return " ";
+ return new WPStrava_StaticGMap();
}
/**
* From an encoded polyline, get the start and finish points for
* the purposes of displaying start and finish markers.
*
- * @static
* @see https://developers.google.com/maps/documentation/utilities/polylinealgorithm
- * @access private
* @param string $enc Encoded polyline.
* @return array {
* Indexes of start & finish containing lat/lon for each.
@@ -76,7 +48,7 @@ class WPStrava_StaticMap {
* }
* }
*/
- private static function decode_start_finish( $enc ) {
+ protected function decode_start_finish( $enc ) {
require_once WPSTRAVA_PLUGIN_DIR . 'src/Polyline.php';
$points = Polyline::decode( $enc );
$points = Polyline::pair( $points );
@@ -91,13 +63,13 @@ class WPStrava_StaticMap {
* From a (large) encoded polyline, reduce the number of points
* until it is small enough for a GET URL.
*
- * @param int $url_len Length of map URL.
- * @param string $enc Encoded polyline.
- * @return string Smaller encoded polyline.
+ * @param int $base_url_len Length of map URL.
+ * @param string $enc Encoded polyline.
+ * @return string Smaller encoded polyline.
* @author Justin Foell
- * @since 2.10.0
+ * @since 2.10
*/
- private static function reduce_polyline( $url_len, $enc ) {
+ protected function reduce_polyline( $base_url_len, $enc ) {
require_once WPSTRAVA_PLUGIN_DIR . 'src/Polyline.php';
$points = Polyline::decode( $enc );
$points = Polyline::pair( $points );
@@ -109,11 +81,23 @@ class WPStrava_StaticMap {
$points = Polyline::flatten( $points );
$polyline = Polyline::encode( $points );
- if ( $url_len + strlen( $polyline ) >= self::$max_chars ) {
+ if ( $base_url_len + $this->polyline_length( $polyline ) >= self::$max_chars ) {
// Reduce again.
- $polyline = self::reduce_polyline( $url_len, $polyline );
+ $polyline = $this->reduce_polyline( $base_url_len, $polyline );
}
return $polyline;
}
+
+ /**
+ * Get the length of a polyline.
+ *
+ * @param mixed $polyline Polyline string.
+ * @return int Polyline string length.
+ * @author Justin Foell
+ * @since 2.11
+ */
+ protected function polyline_length( $polyline ) {
+ return strlen( $polyline );
+ }
}
diff --git a/src/WPStrava/StaticMapbox.php b/src/WPStrava/StaticMapbox.php
new file mode 100644
index 0000000..ffe28d3
--- /dev/null
+++ b/src/WPStrava/StaticMapbox.php
@@ -0,0 +1,94 @@
+map->polyline ) ) {
+ $polyline = $activity->map->polyline;
+ } elseif ( ! empty( $activity->map->summary_polyline ) ) {
+ $polyline = $activity->map->summary_polyline;
+ }
+
+ if ( empty( $polyline ) ) {
+ // No polyline provided.
+ return '';
+ }
+
+ if ( ! $height || ! $width ) {
+ $height = 320;
+ $width = 480;
+ }
+
+ $url = $this->build_url( $polyline, $height, $width, $markers );
+
+ $url_len = strlen( $url );
+ if ( $url_len > self::$max_chars ) {
+ // Need to reduce the polyline b/c it's too big.
+ $polyline = $this->reduce_polyline( $url_len - $this->polyline_length( $polyline ), $polyline );
+ $url = $this->build_url( $polyline, $height, $width, $markers );
+ }
+
+ $title_attr = $title ? " title='" . esc_attr( $title ) . "'" : '';
+ return " ";
+ }
+
+ /**
+ * Build a Mapbox Static Map URL.
+ *
+ * @param string $polyline Polyline string to overlay.
+ * @param int $height Height of map in pixels.
+ * @param int $width Width of map in pixels.
+ * @param bool $markers Display start and finish markers.
+ * @return string Image URL.
+ * @author Justin Foell
+ * @since 2.11
+ */
+ private function build_url( $polyline, $height = 320, $width = 480, $markers = false ) {
+
+ $url = 'https://api.mapbox.com/styles/v1/mapbox/outdoors-v11/static/';
+ $size = "auto/{$width}x{$height}@2x";
+ $token = WPStrava::get_instance()->settings->mapbox_token;
+
+ $path = array();
+
+ if ( $markers ) {
+ $points = $this->decode_start_finish( $polyline );
+ $path[] = "pin-s+008000({$points['start'][0]},{$points['start'][1]})";
+ $path[] = "pin-s+ff0000({$points['finish'][0]},{$points['finish'][1]})";
+ }
+
+ // polyline must be URL encoded https://stackoverflow.com/a/65523379/2146022
+ $url_polyline = rawurlencode( $polyline );
+ $path[] = "path-2+ff0000({$url_polyline})";
+ $url .= implode( ',', $path ) . "/{$size}?access_token={$token}";
+
+ return $url;
+ }
+
+ /**
+ * Get the length of a polyline after encoding.
+ *
+ * @param mixed $polyline Polyline string.
+ * @return int Encoded polyline string length.
+ * @author Justin Foell
+ * @since 2.11
+ */
+ protected function polyline_length( $polyline ) {
+ return strlen( rawurlencode( $polyline ) );
+ }
+}
diff --git a/src/admin-settings.js b/src/admin-settings.js
new file mode 100644
index 0000000..abea924
--- /dev/null
+++ b/src/admin-settings.js
@@ -0,0 +1,50 @@
+window.addEventListener( 'load', function() {
+ strava_toggle_map_type(); // Initial load toggle.
+ document.getElementById( 'strava_map_type' ).addEventListener( 'input', function( e ) {
+ if ( 'SELECT' === e.target.tagName ) {
+ strava_toggle_map_type(); // On change toggle.
+ }
+ }, false );
+} );
+
+/**
+ * Toggle Mapbox / GMaps fields & instructions.
+ */
+function strava_toggle_map_type() {
+ var select = document.getElementById( 'strava_map_type' ),
+ map_type = select.options[select.selectedIndex].value
+ mapbox_id = 'strava_mapbox_token',
+ gmaps_id = 'strava_gmaps_key',
+ mapbox_ins = 'strava-maps-mapbox-instructions',
+ gmaps_ins = 'strava-maps-gmaps-instructions';
+
+ // Toggle Instructions.
+ var mapbox_text = document.getElementById( mapbox_ins );
+ if ( 'mapbox' === map_type ) {
+ if ( mapbox_text.classList.contains( 'hidden' ) ) {
+ mapbox_text.classList.remove( 'hidden' );
+ }
+ } else {
+ mapbox_text.classList.add( 'hidden' );
+ }
+
+ var gmaps_text = document.getElementById( gmaps_ins );
+ if ( 'mapbox' !== map_type ) {
+ if ( gmaps_text.classList.contains( 'hidden' ) ) {
+ gmaps_text.classList.remove( 'hidden' );
+ }
+ } else {
+ gmaps_text.classList.add( 'hidden' );
+ }
+
+ // Toggle Inputs.
+ var mapbox_row = document.getElementById( mapbox_id ).closest( 'tr' );
+ if ( mapbox_row ) {
+ mapbox_row.style.display = ( 'mapbox' === map_type ) ? '' : 'none';
+ }
+
+ var gmaps_row = document.getElementById( gmaps_id ).closest( 'tr' );
+ if ( gmaps_row ) {
+ gmaps_row.style.display = ( 'mapbox' !== map_type ) ? '' : 'none';
+ }
+}