diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..0508865
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+.gitattributes export-ignore
+.gitignore export-ignore
diff --git a/.gitignore b/.gitignore
index e0c38e3..2e8a44a 100755
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
*~
.svn
+.vscode
diff --git a/lib/API.class.php b/lib/API.class.php
index 7df3aa0..66e8e73 100755
--- a/lib/API.class.php
+++ b/lib/API.class.php
@@ -9,7 +9,7 @@ class WPStrava_API {
//const STRAVA_V2_API = 'http://www.strava.com/api/v2/'; //rides/:ride_id/map_details
const STRAVA_V3_API = 'https://www.strava.com/api/v3/';
- public function __construct( $access_token ) {
+ public function __construct( $access_token = null ) {
$this->access_token = $access_token;
}
@@ -19,11 +19,13 @@ class WPStrava_API {
$args = array(
'body' => http_build_query( $data ),
'sslverify' => false,
- 'headers' => array(
- 'Authorization' => 'Bearer ' . $this->access_token,
- )
+ 'headers' => array(),
);
+ if ( $this->access_token ) {
+ $args['headers']['Authorization'] = 'Bearer ' . $this->access_token;
+ }
+
$response = wp_remote_post( $url . $uri, $args );
if ( is_wp_error( $response ) )
@@ -38,9 +40,12 @@ class WPStrava_API {
else
$error = print_r( $response, true );
- return new WP_Error( 'wp-strava_post',
- sprintf( __( 'ERROR %s %s - %s', 'wp-strava'), $response['response']['code'], $response['response']['message'], $error ),
- $response );
+ return new WP_Error(
+ 'wp-strava_post',
+ // translators: message shown when there's a problem with ab HTTP POST to the Strava API.
+ sprintf( __( 'ERROR %1$s %2$s - See full error by adding define( \'WP_STRAVA_DEBUG\' true ); to wp-config.php', 'wp-strava' ), $response['response']['code'], $response['response']['message'] ),
+ $error
+ );
}
return json_decode( $response['body'] );
@@ -51,14 +56,16 @@ class WPStrava_API {
$url .= $uri;
- if ( ! empty( $args ) )
+ if ( ! empty( $args ) ) {
$url = add_query_arg( $args, $url );
+ }
$get_args = array(
- 'headers' => array(
- 'Authorization' => 'Bearer ' . $this->access_token,
- )
+ 'headers' => array(),
);
+ if ( $this->access_token ) {
+ $get_args['headers']['Authorization'] = 'Bearer ' . $this->access_token;
+ }
$response = wp_remote_get( $url, $get_args );
@@ -76,9 +83,12 @@ class WPStrava_API {
else
$error = print_r( $response, true );
- return new WP_Error( 'wp-strava_get',
- sprintf( __( 'ERROR %s %s - %s', 'wp-strava' ), $response['response']['code'], $response['response']['message'], $error ),
- $response );
+ return new WP_Error(
+ 'wp-strava_get',
+ // translators: message shown when there's a problem with an HTTP GET to the Strava API.
+ sprintf( __( 'ERROR %1$s %2$s - See full error by adding define( \'WP_STRAVA_DEBUG\' true ); to wp-config.php', 'wp-strava' ), $response['response']['code'], $response['response']['message'] ),
+ $error
+ );
}
return json_decode( $response['body'] );
diff --git a/lib/RideShortcode.class.php b/lib/ActivityShortcode.class.php
similarity index 83%
rename from lib/RideShortcode.class.php
rename to lib/ActivityShortcode.class.php
index 975e392..92289db 100644
--- a/lib/RideShortcode.class.php
+++ b/lib/ActivityShortcode.class.php
@@ -1,6 +1,6 @@
0,
- 'som' => WPStrava::get_instance()->settings->som,
- 'map_width' => '480',
- 'map_height' => '320',
+ 'id' => 0,
+ 'som' => WPStrava::get_instance()->settings->som,
+ 'map_width' => '480',
+ 'map_height' => '320',
+ 'athlete_token' => WPStrava::get_instance()->settings->get_default_token(),
);
extract( shortcode_atts( $defaults, $atts ) );
$strava_som = WPStrava_SOM::get_som( $som );
- $strava_ride = WPStrava::get_instance()->rides;
- $ride_details = $strava_ride->getRide( $id );
+ $activity = WPStrava::get_instance()->rides;
+ $ride_details = $activity->getRide( $athlete_token, $id );
//sanitize width & height
- $map_width = str_replace( '%', '', $map_width );
+ $map_width = str_replace( '%', '', $map_width );
$map_height = str_replace( '%', '', $map_height );
- $map_width = str_replace( 'px', '', $map_width );
+ $map_width = str_replace( 'px', '', $map_width );
$map_height = str_replace( 'px', '', $map_height );
if ( $ride_details ) {
@@ -82,4 +83,4 @@ class WPStrava_RideShortcode {
}
// Initialize short code
-WPStrava_RideShortcode::init();
+WPStrava_ActivityShortcode::init();
diff --git a/lib/LatestMapWidget.class.php b/lib/LatestMapWidget.class.php
index 65b7940..89d925a 100644
--- a/lib/LatestMapWidget.class.php
+++ b/lib/LatestMapWidget.class.php
@@ -10,13 +10,15 @@ class WPStrava_LatestMapWidget extends WP_Widget {
parent::__construct(
false,
__( 'Strava Latest Map', 'wp-strava' ), // Name
- array( 'description' => __( 'Strava latest ride using static google map image', 'wp-strava' ) ) // Args.
+ array( 'description' => __( 'Strava latest activity using static google map image', 'wp-strava' ) ) // Args.
);
}
public function form( $instance ) {
// outputs the options form on admin
- $title = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : __( 'Latest Activity', 'wp-strava' );
+ $title = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : __( 'Latest Activity Map', 'wp-strava' );
+ $all_tokens = WPStrava::get_instance()->settings->get_all_tokens();
+ $athlete_token = isset( $instance['athlete_token'] ) ? esc_attr( $instance['athlete_token'] ) : WPStrava::get_instance()->settings->get_default_token();
$distance_min = isset( $instance['distance_min'] ) ? esc_attr( $instance['distance_min'] ) : '';
$strava_club_id = isset( $instance['strava_club_id'] ) ? esc_attr( $instance['strava_club_id'] ) : '';
@@ -28,6 +30,14 @@ class WPStrava_LatestMapWidget extends WP_Widget {
+ + +
@@ -43,6 +53,7 @@ class WPStrava_LatestMapWidget extends WP_Widget { // processes widget options to be saved from the admin $instance = $old_instance; $instance['title'] = strip_tags( $new_instance['title'] ); + $instance['athlete_token'] = strip_tags( $new_instance['athlete_token'] ); $instance['strava_club_id'] = strip_tags( $new_instance['strava_club_id'] ); $instance['distance_min'] = strip_tags( $new_instance['distance_min'] ); return $instance; @@ -51,23 +62,25 @@ class WPStrava_LatestMapWidget extends WP_Widget { public function widget( $args, $instance ) { extract( $args ); - $title = apply_filters( 'widget_title', empty( $instance['title'] ) ? __( 'Latest Activity', 'wp-strava' ) : $instance['title'] ); - $distance_min = $instance['distance_min']; + $title = apply_filters( 'widget_title', empty( $instance['title'] ) ? __( 'Latest Activity Map', 'wp-strava' ) : $instance['title'] ); + $athlete_token = isset( $instance['athlete_token'] ) ? $instance['athlete_token'] : WPStrava::get_instance()->settings->get_default_token(); + $distance_min = empty( $instance['distance_min'] ) ? 0 : absint( $instance['distance_min'] ); $strava_club_id = empty( $instance['strava_club_id'] ) ? null : $instance['strava_club_id']; $build_new = false; // Try our transient first. - $ride_transient = get_transient( 'strava_latest_map_ride' ); - $ride_option = get_option( 'strava_latest_map_ride' ); + $ride_transient = get_transient( 'strava_latest_map_activity_' . $athlete_token ); + $ride_option = get_option( 'strava_latest_map_activity_' . $athlete_token ); - $ride = $ride_transient ?: null; + $ride = $ride_transient ? $ride_transient : null; if ( ! $ride ) { $strava_rides = WPStrava::get_instance()->rides; - $rides = $strava_rides->getRides( $strava_club_id ); + $rides = $strava_rides->getRides( $athlete_token, $strava_club_id ); if ( is_wp_error( $rides ) ) { echo $before_widget; + if ( $title ) echo $before_title . $title . $after_title; if ( WPSTRAVA_DEBUG ) { echo '
';
print_r($rides);
@@ -86,14 +99,16 @@ class WPStrava_LatestMapWidget extends WP_Widget {
$ride = current( $rides );
- //update transients & options
+ // Compare transient (temporary storage) to option (more permenant).
+ // If the option isn't set or the transient is different, update the option.
if ( empty( $ride_option->id ) || $ride->id != $ride_option->id ) {
$build_new = true;
- update_option( 'strava_latest_map_ride', $ride );
+ $this->update_activity( $athlete_token, $ride );
}
+ // Update the transient if it needs updating.
if ( empty( $ride_transient->id ) || $ride->id != $ride_transient->id ) {
- set_transient( 'strava_latest_map_ride', $ride, HOUR_IN_SECONDS );
+ $this->update_activity_transient( $athlete_token, $ride );
}
}
}
@@ -102,22 +117,81 @@ class WPStrava_LatestMapWidget extends WP_Widget {
echo $before_widget;
if ( $title ) echo $before_title . $title . $after_title;
?>getStaticImage( $ride->id, $build_new );
+ echo $this->getStaticImage( $athlete_token, $ride, $build_new );
?>rides->getRide( $ride_id );
$img = WPStrava_StaticMap::get_image_tag( $ride );
- update_option( 'strava_latest_map', $img );
+ $this->update_map( $athlete_token, $img );
}
return $img;
}
+
+ /**
+ * Update map in option to cache.
+ *
+ * @author Justin Foell
+ * @since 1.2.0
+ *
+ * @param string $athlete_token Token for athelete.
+ * @param string $img Image tag.
+ */
+ private function update_map( $athlete_token, $img ) {
+ // Remove old (pre 1.2.0) cached maps.
+ if ( get_option( 'strava_latest_map' ) ) {
+ delete_option( 'strava_latest_map' );
+ }
+ update_option( 'strava_latest_map_' . $athlete_token, $img );
+ }
+
+ /**
+ * Update activity in option to cache.
+ *
+ * @author Justin Foell
+ * @since 1.2.0
+ *
+ * @param string $athlete_token Token for athelete.
+ * @param object $activity stdClass Strava activity object.
+ */
+ private function update_activity( $athlete_token, $activity ) {
+ // Remove old (pre 1.2.0) option.
+ if ( get_option( 'strava_latest_map_ride' ) ) {
+ delete_option( 'strava_latest_map_ride' );
+ }
+ update_option( 'strava_latest_map_activity_' . $athlete_token, $activity );
+ }
+
+ /**
+ * Update activity in transient to cache.
+ *
+ * @author Justin Foell
+ * @since 1.2.0
+ *
+ * @param string $athlete_token Token for athelete.
+ * @param object $activity stdClass Strava activity object.
+ */
+ private function update_activity_transient( $athlete_token, $activity ) {
+ // Remove old (pre 1.2.0) transient.
+ if ( get_transient( 'strava_latest_map_ride' ) ) {
+ delete_transient( 'strava_latest_map_ride' );
+ }
+ set_transient( 'strava_latest_map_activity_' . $athlete_token, $activity, HOUR_IN_SECONDS );
+ }
}
diff --git a/lib/LatestRidesWidget.class.php b/lib/LatestRidesWidget.class.php
index bcbaf42..2a3174f 100644
--- a/lib/LatestRidesWidget.class.php
+++ b/lib/LatestRidesWidget.class.php
@@ -7,7 +7,7 @@ class WPStrava_LatestRidesWidget extends WP_Widget {
public function __construct() {
$widget_ops = array( 'classname' => 'LatestRidesWidget', 'description' => __( 'Will publish your latest rides activity from strava.com.', 'wp-strava' ) );
- parent::__construct( 'wp-strava', $name = __( 'Strava Latest Rides', 'wp-strava' ), $widget_ops );
+ parent::__construct( 'wp-strava', $name = __( 'Strava Latest Activity List', 'wp-strava' ), $widget_ops );
add_action( 'wp_enqueue_scripts', array( $this, 'maybe_enqueue' ) );
}
@@ -22,15 +22,15 @@ class WPStrava_LatestRidesWidget extends WP_Widget {
extract( $args );
//$widget_id = $args['widget_id'];
- $title = apply_filters( 'widget_title', empty( $instance['title'] ) ? __( 'Rides', 'wp-strava' ) : $instance['title'] );
+ $title = apply_filters( 'widget_title', empty( $instance['title'] ) ? __( 'Activity', 'wp-strava' ) : $instance['title'] );
+ $athlete_token = isset( $instance['athlete_token'] ) ? $instance['athlete_token'] : WPStrava::get_instance()->settings->get_default_token();
$strava_club_id = empty( $instance['strava_club_id'] ) ? '' : $instance['strava_club_id'];
$quantity = empty( $instance['quantity'] ) ? '5' : $instance['quantity'];
- $this->som = WPStrava_SOM::get_som();
?>
- strava_request_handler( $strava_club_id, $quantity ); ?>
+ strava_request_handler( $athlete_token, $strava_club_id, $quantity ); ?>
settings->get_all_tokens();
+ $athlete_token = isset( $instance['athlete_token'] ) ? esc_attr( $instance['athlete_token'] ) : WPStrava::get_instance()->settings->get_default_token();
$strava_club_id = isset( $instance['strava_club_id'] ) ? esc_attr( $instance['strava_club_id'] ) : '';
$quantity = isset( $instance['quantity'] ) ? absint( $instance['quantity'] ) : 5;
@@ -57,7 +60,15 @@ class WPStrava_LatestRidesWidget extends WP_Widget {
-
+
+
+
+
+
@@ -69,11 +80,12 @@ class WPStrava_LatestRidesWidget extends WP_Widget {
// The handler to the ajax call, we will avoid this if Strava support jsonp request and we can do it
// the parsing directly on the jQuery ajax call, the returned text will be enclosed in the $response variable.
- private function strava_request_handler( $strava_club_id, $quantity ) {
+ private function strava_request_handler( $athlete_token, $strava_club_id, $quantity ) {
+ $som = WPStrava_SOM::get_som();
$strava_rides = WPStrava::get_instance()->rides;
- $rides = $strava_rides->getRides( $strava_club_id, $quantity );
+ $rides = $strava_rides->getRides( $athlete_token, $strava_club_id, $quantity );
if ( is_wp_error( $rides ) )
return $rides->get_error_message();
@@ -89,9 +101,9 @@ class WPStrava_LatestRidesWidget extends WP_Widget {
$response .= " " . $ride->athlete_name . '';
}
- $response .= sprintf( __( ' rode %s %s', 'wp-strava' ), $this->som->distance( $ride->distance ), $this->som->get_distance_label() );
- $response .= sprintf( __( ' during %s %s', 'wp-strava' ), $this->som->time( $ride->elapsed_time ), $this->som->get_time_label() );
- $response .= sprintf( __( ' climbing %s %s', 'wp-strava' ), $this->som->elevation( $ride->total_elevation_gain ), $this->som->get_elevation_label() );
+ $response .= sprintf( __( ' rode %s %s', 'wp-strava' ), $som->distance( $ride->distance ), $som->get_distance_label() );
+ $response .= sprintf( __( ' during %s %s', 'wp-strava' ), $som->time( $ride->elapsed_time ), $som->get_time_label() );
+ $response .= sprintf( __( ' climbing %s %s', 'wp-strava' ), $som->elevation( $ride->total_elevation_gain ), $som->get_elevation_label() );
$response .= "";
$response .= "";
}
diff --git a/lib/Rides.class.php b/lib/Rides.class.php
index 4b237ff..0fb5bd1 100755
--- a/lib/Rides.class.php
+++ b/lib/Rides.class.php
@@ -7,12 +7,30 @@ class WPStrava_Rides {
const RIDES_URL = 'http://app.strava.com/rides/';
const ATHLETES_URL = 'http://app.strava.com/athletes/';
- public function getRide( $rideId ) {
- return WPStrava::get_instance()->api->get( "activities/{$rideId}" );
+ /**
+ * Get single activity by ID.
+ *
+ * @param string $athlete_token Token of athlete to retrieve for
+ * @param int $activity_id ID of activity to retrieve.
+ * @return object stdClass representing this activty.
+ * @author Justin Foell
+ */
+ public function getRide( $athlete_token, $activity_id ) {
+ return WPStrava::get_instance()->get_api( $athlete_token )->get( "activities/{$activity_id}" );
} // getRideDetails
- public function getRides( $club_id = null, $quantity = null ) {
- $api = WPStrava::get_instance()->api;
+ /**
+ * Get activity list from Strava API.
+ *
+ * @author Justin Foell
+ *
+ * @param string $athlete_token Token of athlete to retrieve for
+ * @param int $club_id Club ID of all club riders (optional).
+ * @param int|null $quantity Number of records to retrieve (optional).
+ * @return array|WP_Error Array of rides or WP_Error.
+ */
+ public function getRides( $athlete_token, $club_id = null, $quantity = null ) {
+ $api = WPStrava::get_instance()->get_api( $athlete_token );
$data = null;
@@ -25,11 +43,13 @@ class WPStrava_Rides {
$data = $api->get( 'athlete/activities', $args );
}
- if ( is_wp_error( $data ) )
+ if ( is_wp_error( $data ) ) {
return $data;
+ }
- if ( is_array( $data ) )
+ if ( is_array( $data ) ) {
return $data;
+ }
return array();
diff --git a/lib/Settings.class.php b/lib/Settings.class.php
index 4161fa8..368f94e 100644
--- a/lib/Settings.class.php
+++ b/lib/Settings.class.php
@@ -1,7 +1,7 @@
tokens_empty( $_POST['strava_token'] ) )
+ return array();
+
// Redirect only if all the right options are in place.
- if ( isset( $value[0]['type'] ) && $value[0]['type'] == 'updated' ) { // Make sure there were no settings errors.
+ if ( isset( $value[0]['type'] ) && 'updated' == $value[0]['type'] ) { // Make sure there were no settings errors.
if ( isset( $_POST['option_page'] ) && $_POST['option_page'] == $this->option_page ) { // Make sure we're on our settings page.
- // User is clearing to start-over, don't oauth.
- if ( isset( $_POST['strava_token'] ) && empty( $_POST['strava_token'] ) )
- return;
-
- // Only re-auth if client ID and secret were shown.
+ // Only re-auth if client ID and secret were saved.
if ( ! empty( $_POST['strava_client_id'] ) && ! empty( $_POST['strava_client_secret'] ) ) {
- $client_id = get_option( 'strava_client_id' );
- $client_secret = get_option( 'strava_client_secret' );
+ $client_id = $_POST['strava_client_id'];
+ $client_secret = $_POST['strava_client_secret'];
- if ( $client_id && $client_secret ) {
- $redirect = admin_url( "options-general.php?page={$this->page_name}" );
- $url = "https://www.strava.com/oauth/authorize?client_id={$client_id}&response_type=code&redirect_uri={$redirect}&approval_prompt=force";
- wp_redirect( $url );
- exit();
- }
+ $redirect = admin_url( "options-general.php?page={$this->page_name}" );
+ $url = "https://www.strava.com/oauth/authorize?client_id={$client_id}&response_type=code&redirect_uri={$redirect}&approval_prompt=force";
+ wp_redirect( $url );
+ exit();
}
}
}
@@ -61,30 +61,37 @@ class WPStrava_Settings {
}
public function add_strava_menu() {
- add_options_page( __( 'Strava Settings', 'wp-strava' ),
- __( 'Strava', 'wp-strava' ),
- 'manage_options',
- $this->page_name,
- array( $this, 'print_strava_options' ) );
+ add_options_page(
+ __( 'Strava Settings', 'wp-strava' ),
+ __( 'Strava', 'wp-strava' ),
+ 'manage_options',
+ $this->page_name,
+ array( $this, 'print_strava_options' )
+ );
}
public function init() {
+ $this->tokens = $this->get_tokens();
+
+ // Only validate additional athlete information if all fields are present.
+ $this->adding_athlete = ! ( empty( $_POST['strava_client_id'] ) && empty( $_POST['strava_client_secret'] ) );
+
//only update when redirected back from strava
if ( ! isset( $_GET['settings-updated'] ) && isset( $_GET['page'] ) && $_GET['page'] == $this->page_name ) {
if ( isset( $_GET['code'] ) ) {
- $token = $this->get_token( $_GET['code'] );
+ $token = $this->fetch_token( $_GET['code'] );
if ( $token ) {
add_settings_error( 'strava_token', 'strava_token', sprintf( __( 'New Strava token retrieved. %s', 'wp-strava' ), $this->feedback ) , 'updated' );
- update_option( 'strava_token', $token );
+ $this->add_token( $token );
+ update_option( 'strava_token', $this->tokens );
} else {
add_settings_error( 'strava_token', 'strava_token', $this->feedback );
}
- } else if ( isset( $_GET['error'] ) ) {
+ } elseif ( isset( $_GET['error'] ) ) {
+ // Translators: authentication error mess
add_settings_error( 'strava_token', 'strava_token', sprintf( __( 'Error authenticating at Strava: %s', 'wp-strava' ), str_replace( '_', ' ', $_GET['error'] ) ) );
}
}
-
- $this->token = get_option( 'strava_token' );
}
public function register_strava_settings() {
@@ -92,15 +99,26 @@ class WPStrava_Settings {
add_settings_section( 'strava_api', __( 'Strava API', 'wp-strava' ), array( $this, 'print_api_instructions' ), 'wp-strava' );
- if ( ! $this->token ) {
+ if ( $this->tokens_empty( $this->tokens ) ) {
register_setting( $this->option_page, 'strava_client_id', array( $this, 'sanitize_client_id' ) );
register_setting( $this->option_page, 'strava_client_secret', array( $this, 'sanitize_client_secret' ) );
+ register_setting( $this->option_page, 'strava_nickname', array( $this, 'sanitize_nickname' ) );
add_settings_field( 'strava_client_id', __( 'Strava Client ID', 'wp-strava' ), array( $this, 'print_client_input' ), 'wp-strava', 'strava_api' );
add_settings_field( 'strava_client_secret', __( 'Strava Client Secret', 'wp-strava' ), array( $this, 'print_secret_input' ), 'wp-strava', 'strava_api' );
+ add_settings_field( 'strava_nickname', __( 'Strava Nickname', 'wp-strava' ), array( $this, 'print_nickname_input' ), 'wp-strava', 'strava_api' );
} else {
register_setting( $this->option_page, 'strava_token', array( $this, 'sanitize_token' ) );
add_settings_field( 'strava_token', __( 'Strava Token', 'wp-strava' ), array( $this, 'print_token_input' ), 'wp-strava', 'strava_api' );
+
+ // Add additional fields
+ register_setting( $this->option_page, 'strava_client_id', array( $this, 'sanitize_client_id' ) );
+ register_setting( $this->option_page, 'strava_client_secret', array( $this, 'sanitize_client_secret' ) );
+ register_setting( $this->option_page, 'strava_nickname', array( $this, 'sanitize_nickname' ) );
+
+ add_settings_field( 'strava_client_id', __( 'Additional Athlete Client ID', 'wp-strava' ), array( $this, 'print_client_input' ), 'wp-strava', 'strava_api' );
+ add_settings_field( 'strava_client_secret', __( 'Additional Athlete Client Secret', 'wp-strava' ), array( $this, 'print_secret_input' ), 'wp-strava', 'strava_api' );
+ add_settings_field( 'strava_nickname', __( 'Additional Athlete Nickname', 'wp-strava' ), array( $this, 'print_nickname_input' ), 'wp-strava', 'strava_api' );
}
// Google Maps API.
@@ -122,30 +140,42 @@ class WPStrava_Settings {
public function print_api_instructions() {
$signup_url = 'http://www.strava.com/developers';
$settings_url = 'https://www.strava.com/settings/api';
- $blog_name = get_bloginfo( 'name' );
- $app_name = sprintf( esc_html( '%s Strava', 'wp-strava' ), $blog_name );
+ $icon_url = 'https://plugins.svn.wordpress.org/wp-strava/assets/icon-128x128.png';
+ $blog_name = get_bloginfo( 'name' );
+ $app_name = sprintf( esc_html( '%s Strava', 'wp-strava' ), $blog_name );
$site_url = site_url();
$description = 'WP-Strava for ' . $blog_name;
- printf( __( "
Steps:
+ printf( __( "Steps:
- - Create your free API Application/Connection here: %s using the following information:
+ - Create your free API Application/Connection here: %2\$s using the following information:
- - Application Name: %s
- - Website: %s
- - Application Description: %s
- - Authorization Callback Domain: %s
+ - App Icon: upload this image
+ - Application Name: %4\$s
+ - Category: OK to leave at default 'other'
+ - Club: OK to leave blank
+ - Website: %5\$s
+ - Application Description: %6\$s
+ - Authorization Callback Domain: %7\$s
- Once you've created your API Application at strava.com, enter the Client ID and Client Secret below, which can now be found on that same strava API Settings page.
- After saving your Client ID and Secret, you'll be redirected to strava to authorize your API Application. If successful, your Strava Token will display instead of Client ID and Client Secret.
- If you need to re-authorize your API Application, erase your Strava Token here and click 'Save Changes' to start over.
-
", 'wp-strava' ), $settings_url, $settings_url, $app_name, $site_url, $description, $site_url );
+ ", 'wp-strava' ),
+ $settings_url,
+ $settings_url,
+ $icon_url,
+ $app_name,
+ $site_url,
+ $description,
+ wp_parse_url( $site_url, PHP_URL_HOST )
+ );
}
public function print_gmaps_instructions() {
$maps_url = 'https://developers.google.com/maps/documentation/static-maps/';
- printf( __( "Steps:
+ printf( __( "Steps:
- - To use Google map images, you must create a Static Maps API Key. Create a free key by going here: %s and clicking Get a Key
+ - 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 );
@@ -155,14 +185,14 @@ class WPStrava_Settings {
?>
-
-
+
+
@@ -170,18 +200,34 @@ class WPStrava_Settings {
}
public function print_client_input() {
- ?>tokens_empty( $this->tokens ) ? __( 'Default', 'wp-strava' ) : '';
+ ?>get_all_tokens() as $token => $nickname ) {
+ ?>
+
+
+
+ adding_athlete ) {
+ return $client_id;
+ }
+
if ( ! is_numeric( $client_id ) ) {
add_settings_error( 'strava_client_id', 'strava_client_id', __( 'Client ID must be a number.', 'wp-strava' ) );
}
@@ -189,23 +235,61 @@ class WPStrava_Settings {
}
public function sanitize_client_secret( $client_secret ) {
- if ( trim( $client_secret ) == '' ) {
+ // Return early if not trying to add an additional athlete.
+ if ( ! $this->adding_athlete ) {
+ return $client_secret;
+ }
+
+ if ( '' == trim( $client_secret ) ) {
add_settings_error( 'strava_client_secret', 'strava_client_secret', __( 'Client Secret is required.', 'wp-strava' ) );
}
return $client_secret;
}
+ public function sanitize_nickname( $nicknames ) {
+ if ( ! $this->adding_athlete ) {
+
+ // Chop $nicknames to same size as tokens.
+ $nicknames = array_slice( $nicknames, 0, count( $_POST['strava_token'] ) );
+
+ // Remove indexes from $nicknames that have empty tokens.
+ foreach( $_POST['strava_token'] as $index => $token ) {
+ $token = trim( $token );
+ if ( empty( $token ) ) {
+ unset( $nicknames[ $index ] );
+ }
+ }
+
+ // Process $nicknames so indexes start with zero.
+ $nicknames = array_merge( $nicknames, array() );
+ }
+
+ foreach ( $nicknames as $index => $nickname ) {
+ if ( '' == trim( $nickname ) ) {
+ add_settings_error( 'strava_nickname', 'strava_nickname', __( 'Nickname is required.', 'wp-strava' ) );
+ return $nicknames;
+ }
+ }
+ return $nicknames;
+ }
+
public function sanitize_token( $token ) {
return $token;
}
- private function get_token( $code ) {
- $client_id = get_option( 'strava_client_id' );
- $client_secret = get_option( 'strava_client_secret' );
+ private function fetch_token( $code ) {
+ $client_id = $this->client_id;
+ $client_secret = $this->client_secret;
+
+ delete_option( 'strava_client_id' );
+ delete_option( 'strava_client_secret' );
if ( $client_id && $client_secret ) {
+ require_once WPSTRAVA_PLUGIN_DIR . 'lib/API.class.php';
+ $api = new WPStrava_API();
$data = array( 'client_id' => $client_id, 'client_secret' => $client_secret, 'code' => $code );
- $strava_info = WPStrava::get_instance()->api->post( 'oauth/token', $data );
+
+ $strava_info = $api->post( 'oauth/token', $data );
if ( $strava_info ) {
if ( isset( $strava_info->access_token ) ) {
@@ -222,11 +306,11 @@ class WPStrava_Settings {
} else {
$this->feedback .= __( 'Missing Client ID or Client Secret.', 'wp-strava' );
return false;
- }
+ } // End if.
}
public function print_gmaps_key_input() {
- ?>
get_tokens() as $token ) {
+ delete_transient( 'strava_latest_map_activity_' . $token );
+ delete_option( 'strava_latest_map_activity_' . $token );
+ delete_option( 'strava_latest_map_' . $token );
+ }
}
return null;
}
+ /**
+ * Gets all saved strava tokens as an array.
+ *
+ * @return array
+ * @author Justin Foell
+ * @since 1.2.0
+ */
+ public function get_tokens() {
+ $tokens = get_option( 'strava_token' );
+ if ( ! is_array( $tokens ) ) {
+ $tokens = array( $tokens );
+ }
+
+ foreach ( $tokens as $index => $token ) {
+ if ( empty( $token ) ) {
+ unset( $tokens[ $index ] );
+ $tokens = array_values( $tokens ); // Rebase array keys after unset @see https://stackoverflow.com/a/5943165/2146022
+ }
+ }
+ return $tokens;
+ }
+
+ /**
+ * Returns first (default) token saved.
+ *
+ * @return string|null
+ * @author Justin Foell
+ * @since 1.2.0
+ */
+ public function get_default_token() {
+ $tokens = $this->get_tokens();
+ return isset( $tokens[0] ) ? $tokens[0] : null;
+ }
+
+ /**
+ * Get all tokens and their nicknames in one array.
+ *
+ * @return void
+ * @author Justin Foell
+ * @since 1.2.0
+ */
+ public function get_all_tokens() {
+ $tokens = $this->get_tokens();
+ $nicknames = $this->nickname;
+ $all = array();
+ $number = 1;
+ foreach ( $tokens as $index => $token ) {
+ if ( ! empty( $nicknames[ $index ] ) ) {
+ $all[ $token ] = $nicknames[ $index ];
+ } else {
+ $all[ $token ] = $this->get_default_nickname( $number );
+ }
+ $number++;
+ }
+ return $all;
+ }
+
+ /**
+ * Returns default nickname 'Default' / 'Athlete n'.
+ *
+ * @author Justin Foell
+ * @since 1.2.0
+ *
+ * @param integer $number Athlete number (default 1).
+ * @return string
+ */
+ private function get_default_nickname( $number = 1 ) {
+ // Translators: Athelete number if no nickname present.
+ return ( 1 == $number ) ? __( 'Default', 'wp-strava' ) : sprintf( __( 'Athlete %s', 'wp-strava' ), $number );
+ }
+
+ /**
+ * Checks for valid tokens.
+ *
+ * @author Justin Foell
+ * @since 1.2.0
+ *
+ * @param string|array Single token or array of tokens.
+ * @return boolean True if empty.
+ */
+ public function tokens_empty( $tokens ) {
+ if ( empty( $tokens ) ) {
+ return true;
+ }
+
+ if ( is_array( $tokens ) ) {
+ foreach( $tokens as $token ) {
+ if ( ! empty( $token ) ) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Only add a token if it's not already there.
+ *
+ * @param string $token
+ *
+ * @author Justin Foell
+ * @since 1.2.0
+ */
+ public function add_token( $token ) {
+ if ( false === array_search( $token, $this->tokens ) ) {
+ $this->tokens[] = $token;
+ }
+ }
+
public function __get( $name ) {
- return get_option( "strava_{$name}" );
+ if ( ! strpos( 'strava_', $name ) ) {
+ $name = "strava_{$name}";
+ }
+ // Else.
+ return get_option( $name );
}
public function settings_link( $links ) {
@@ -271,4 +475,10 @@ class WPStrava_Settings {
return $links;
}
+ public function settings_scripts() {
+ $screen = get_current_screen();
+ if ( "settings_page_{$this->page_name}" === $screen->id ) {
+ wp_enqueue_script( 'wp-strava-settings', WPSTRAVA_PLUGIN_URL . 'js/wp-strava-settings.js', array( 'jquery' ) );
+ }
+ }
}
diff --git a/lib/StaticMap.class.php b/lib/StaticMap.class.php
index bb214c9..38a9e29 100644
--- a/lib/StaticMap.class.php
+++ b/lib/StaticMap.class.php
@@ -27,7 +27,7 @@ class WPStrava_StaticMap {
if ( ! empty( $ride->map->polyline ) && ( $url_len + strlen( $ride->map->polyline ) < $max_chars ) ) {
$url .= $ride->map->polyline;
- } else {
+ } elseif ( ! empty( $ride->map->summary_polyline ) ) {
$url .= $ride->map->summary_polyline;
}
diff --git a/lib/Strava.class.php b/lib/Strava.class.php
index cb8f9f1..375f751 100644
--- a/lib/Strava.class.php
+++ b/lib/Strava.class.php
@@ -4,14 +4,14 @@ require_once WPSTRAVA_PLUGIN_DIR . 'lib/Settings.class.php';
require_once WPSTRAVA_PLUGIN_DIR . 'lib/SOM.class.php';
require_once WPSTRAVA_PLUGIN_DIR . 'lib/LatestRidesWidget.class.php';
require_once WPSTRAVA_PLUGIN_DIR . 'lib/LatestMapWidget.class.php';
-require_once WPSTRAVA_PLUGIN_DIR . 'lib/RideShortcode.class.php';
+require_once WPSTRAVA_PLUGIN_DIR . 'lib/ActivityShortcode.class.php';
require_once WPSTRAVA_PLUGIN_DIR . 'lib/StaticMap.class.php';
class WPStrava {
private static $instance = null;
private $settings = null;
- private $api = null;
+ private $api = array(); // Holds an array of APIs.
private $rides = null;
private function __construct() {
@@ -38,10 +38,6 @@ class WPStrava {
public function __get( $name ) {
// On-demand classes.
- if ( $name == 'api' ) {
- return $this->get_api();
- }
-
if ( $name == 'rides' ) {
return $this->get_rides();
}
@@ -53,13 +49,17 @@ class WPStrava {
return null;
}
- public function get_api() {
- if ( ! $this->api ) {
- require_once WPSTRAVA_PLUGIN_DIR . 'lib/API.class.php';
- $this->api = new WPStrava_API( get_option( 'strava_token' ) );
+ public function get_api( $token = null ) {
+ if ( ! $token ) {
+ $token = $this->settings->get_default_token();
}
- return $this->api;
+ if ( empty( $this->api[ $token ] ) ) {
+ require_once WPSTRAVA_PLUGIN_DIR . 'lib/API.class.php';
+ $this->api[$token] = new WPStrava_API( $token );
+ }
+
+ return $this->api[$token];
}
public function get_rides() {
@@ -75,4 +75,4 @@ class WPStrava {
// Register a personalized stylesheet
wp_register_style( 'wp-strava-style', WPSTRAVA_PLUGIN_URL . 'css/wp-strava.css' );
}
-}
\ No newline at end of file
+}
diff --git a/readme.txt b/readme.txt
index 69f308f..9b553a5 100755
--- a/readme.txt
+++ b/readme.txt
@@ -2,57 +2,65 @@
Contributors: cmanon, jrfoell, lancewillett
Tags: strava, bicycle, cycling, biking, running, run, swimming, swim, gps, shortcode, widget, plugin
Requires at least: 4.6
-Tested up to: 4.7
-Stable tag: 1.1.1
+Tested up to: 4.9
+Stable tag: 1.2.0
License: GPLv2 or later
Show your Strava activity on your WordPress site.
== Description ==
-This plugin uses the Strava V3 API to embed maps and activity for
-athletes and clubs on your WordPress site. Included are several
-widgets and shortcodes for showing maps and activity summaries.
+This plugin uses the Strava API to embed maps and activity for athletes and clubs on your WordPress site. Included are several widgets and shortcodes for showing maps and activity summaries.
= Shortcodes =
-[activity id=NUMBER] - add to any page or post. Also takes the following
-optional parameters:
+[activity id=NUMBER] - add to any page or post. Shows a summary of the activity plus a map if a google maps key has been added.
-* som - english/metric (system of measure - override from default setting)
-* map_width - width (width of image in pixels)
-* map_height - height (height of image in pixels)
+Also takes the following optional parameters:
+
+* som - english/metric (system of measure - override from default setting).
+* map_width - width (width of image in pixels).
+* map_height - height (height of image in pixels).
+* athlete_token - specify a different athlete (you can copy this value from https://www.strava.com/settings/api or the wp-strava settings page at /wp-admin/options-general.php?page=wp-strava-options).
+
+[ride] is an alias for [activity] and will accept the same parameters (kept for backwards compatibility).
= Widgets =
-Strava Latest Rides - shows a list of the last few activities
+Strava Latest Activity List - shows a list of the last few activities.
-Strava Latest Map - shows map of latest activity with option to limit
-latest map to activities of a certain minimum distance
+Strava Latest Map - shows map of latest activity with option to limit latest map to activities of a certain minimum distance.
== Changelog ==
+= 1.2.0 =
+Added multi-athlete configuration.
+Additional transitions from Ride -> Activity.
+Updated setup instructions to reflect latest Strava API set up process.
+Backwards Compatibility - removed PHP 5.3+ specific operator (should work with PHP 5.2 now - versions 1.1 and 1.1.1 don't).
+Reworked error reporting and formatting.
+
= 1.1.1 =
-Changes to better support translations through https://translate.wordpress.org
-Cleaned up formatting
+Changes to better support translations through https://translate.wordpress.org.
+Cleaned up formatting.
= 1.1 =
-Added [activity] shortcode to deprecate [ride] in the future
-Fixed static method call error in shortcode
-Added title to Strava Latest Map Widget
-Added Lance Willett to contributors
-Added target="_blank" to widget hrefs
-Added Google Maps Key to settings (required for map images)
-Added cache clear option to remove transient & image data
-Cleaned up formatting
+Added [activity] shortcode to deprecate [ride] in the future.
+Fixed static method call error in shortcode.
+Added title to Strava Latest Map Widget.
+Added Lance Willett to contributors.
+Added target="_blank" to widget hrefs.
+Added Google Maps Key to settings (required for map images).
+Added cache clear option to remove transient & image data.
+Cleaned up formatting.
= 1.0 =
-Change to Strava API V3
-Switch ride shortcode to use static map
+Change to Strava API V3.
+Switch ride shortcode to use static map.
= 0.70 =
-Use WordPress HTTP API for all remote calls
-Use WordPress Settings API for settings page
+Use WordPress HTTP API for all remote calls.
+Use WordPress Settings API for settings page.
= 0.62 =
Refactor some code.
diff --git a/wp-strava.php b/wp-strava.php
index 622caa1..f78bfa5 100755
--- a/wp-strava.php
+++ b/wp-strava.php
@@ -3,7 +3,7 @@
* Plugin Name: WP Strava
* Plugin URI: https://wordpress.org/plugins/wp-strava/
* Description: Plugin to show your strava.com information in your wordpress blog. Some Icons are Copyright © Yusuke Kamiyamane. All rights reserved. Licensed under a Creative Commons Attribution 3.0 license.
- * Version: 1.1.1
+ * Version: 1.2.0
* Author: Carlos Santa Cruz, Justin Foell, Lance Willet
* License: GPL2
* Text Domain: wp-strava