Merge pull request #31 from cmanon/feature/refresh-auth

Changes for WP-Strava 2.0 (refresh auth)
This commit is contained in:
Justin Foell
2019-10-04 11:47:14 -05:00
committed by GitHub
31 changed files with 654 additions and 258 deletions
+2
View File
@@ -3,3 +3,5 @@
composer.json export-ignore
composer.lock export-ignore
phpcs.xml export-ignore
tests export-ignore
phpunit.xml export-ignore
+16 -7
View File
@@ -16,6 +16,12 @@ class WPStrava {
*/
private $settings = null;
/**
* Authorization object.
* @var WPStrava_Auth
*/
private $auth = null;
/**
* Array of WPStrava_API objects (one for each athlete).
*
@@ -40,6 +46,9 @@ class WPStrava {
*/
private function __construct() {
$this->settings = new WPStrava_Settings();
$this->auth = WPStrava_Auth::get_auth( 'refresh' );
$this->auth->hook();
if ( is_admin() ) {
$this->settings->hook();
@@ -90,21 +99,21 @@ class WPStrava {
}
/**
* Get an API object for the given athelete token.
* Get an API object for the given athlete token.
*
* @param string $token Athlete token.
* @return WPStrava_API
*/
public function get_api( $token = null ) {
if ( ! $token ) {
$token = $this->settings->get_default_token();
public function get_api( $id = null ) {
if ( ! $id ) {
$id = $this->settings->get_default_id();
}
if ( empty( $this->api[ $token ] ) ) {
$this->api[ $token ] = new WPStrava_API( $token );
if ( empty( $this->api[ $id ] ) ) {
$this->api[ $id ] = new WPStrava_API( $id );
}
return $this->api[ $token ];
return $this->api[ $id ];
}
/**
@@ -7,10 +7,27 @@ class WPStrava_API {
const STRAVA_V3_API = 'https://www.strava.com/api/v3/';
public function __construct( $access_token = null ) {
$this->access_token = $access_token;
private $client_id = null;
/**
* Constructor.
*
* @param int $client_id Strava API Client ID representing an athlete.
* @author Justin Foell <justin@foell.org>
*/
public function __construct( $client_id = null ) {
$this->client_id = $client_id;
}
/**
* POST something to the Strava API.
*
* @param string $uri Path within the Strava API.
* @param array $data Data to POST.
* @return stdClass Strava API response.
* @throws WPStrava_Exception
* @author Justin Foell <justin@foell.org>
*/
public function post( $uri, $data = null ) {
$url = self::STRAVA_V3_API;
@@ -21,8 +38,9 @@ class WPStrava_API {
'timeout' => 30,
);
if ( $this->access_token ) {
$args['headers']['Authorization'] = 'Bearer ' . $this->access_token;
$access_token = $this->get_access_token();
if ( $access_token ) {
$args['headers']['Authorization'] = 'Bearer ' . $access_token;
}
$response = wp_remote_post( $url . $uri, $args );
@@ -53,9 +71,19 @@ class WPStrava_API {
return json_decode( $response['body'] );
}
/**
* GET something from the Strava API.
*
* @param string $uri Path within the Strava API.
* @param array $args Request arguments.
* @return stdClass Strava API response.
* @throws WPStrava_Exception
* @author Justin Foell <justin@foell.org>
*/
public function get( $uri, $args = null ) {
$url = self::STRAVA_V3_API;
static $retry = true;
$url = self::STRAVA_V3_API;
$url .= $uri;
if ( ! empty( $args ) ) {
@@ -68,16 +96,28 @@ class WPStrava_API {
'timeout' => 30,
);
if ( $this->access_token ) {
$get_args['headers']['Authorization'] = 'Bearer ' . $this->access_token;
$access_token = $this->get_access_token();
if ( $access_token ) {
$get_args['headers']['Authorization'] = 'Bearer ' . $access_token;
}
$response = wp_remote_get( $url, $get_args );
if ( is_wp_error( $response ) ) {
throw WPStrava_Exception::from_wp_error( $response );
}
// Try *one* real-time token refresh if 404.
if ( $retry && 404 == $response['response']['code'] ) {
$retry = false;
$auth = WPStrava::get_instance()->auth;
if ( $auth instanceof WPStrava_AuthRefresh ) {
$auth->auth_refresh();
return $this->get( $uri, $args );
}
} else {
$retry = true;
}
if ( 200 != $response['response']['code'] ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
// See if there's useful info in the body.
@@ -102,4 +142,25 @@ class WPStrava_API {
return json_decode( $response['body'] );
}
} // Class API.
/**
* Get the (ever changing) access token based on current Client ID.
*
* @return string|null String for access token, null if not found.
* @author Justin Foell <justin@foell.org>
* @since 2.0.0
*/
private function get_access_token() {
// If client_id not set (OAuth set-up), don't even look.
if ( ! $this->client_id ) {
return null;
}
$settings = WPStrava::get_instance()->settings;
$info = $settings->info;
if ( ! empty( $info[ $this->client_id ]->access_token ) ) {
return $info[ $this->client_id ]->access_token;
}
return null;
}
}
@@ -10,26 +10,26 @@ class WPStrava_Activity {
/**
* Get single activity by ID.
*
* @param string $athlete_token Token of athlete to retrieve for
* @param string $client_id Client ID of athlete to retrieve for
* @param int $activity_id ID of activity to retrieve.
* @return object stdClass representing this activity.
* @return object stdClass Representing this activity.
* @author Justin Foell <justin@foell.org>
*/
public function get_activity( $athlete_token, $activity_id ) {
return WPStrava::get_instance()->get_api( $athlete_token )->get( "activities/{$activity_id}" );
public function get_activity( $client_id, $activity_id ) {
return WPStrava::get_instance()->get_api( $client_id )->get( "activities/{$activity_id}" );
}
/**
* Get activity list from Strava API.
*
* @author Justin Foell <justin@foell.org>
* @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).
* @param string $client_id Client ID 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 Array of activities.
*/
public function get_activities( $athlete_token, $club_id = null, $quantity = null ) {
$api = WPStrava::get_instance()->get_api( $athlete_token );
public function get_activities( $client_id, $club_id = null, $quantity = null ) {
$api = WPStrava::get_instance()->get_api( $client_id );
$data = null;
@@ -51,13 +51,18 @@ class WPStrava_ActivityShortcode {
'som' => WPStrava::get_instance()->settings->som,
'map_width' => '480',
'map_height' => '320',
'athlete_token' => WPStrava::get_instance()->settings->get_default_token(),
'client_id' => WPStrava::get_instance()->settings->get_default_id(),
'markers' => false,
'image_only' => false,
);
$atts = shortcode_atts( $defaults, $atts, 'activity' );
if ( isset( $atts['athlete_token'] ) ) {
// Translators: Message shown when using deprecated athlete_token parameter.
return __( 'The <code>athlete_token</code> parameter is deprecated as of version 2 and should be replaced with <code>client_id</code>.', 'wp-strava' );
}
/* Make sure boolean values are actually boolean
* @see https://wordpress.stackexchange.com/a/119299
*/
@@ -68,7 +73,7 @@ class WPStrava_ActivityShortcode {
$activity_details = null;
try {
$activity_details = $activity->get_activity( $atts['athlete_token'], $atts['id'] );
$activity_details = $activity->get_activity( $atts['client_id'], $atts['id'] );
} catch ( WPStrava_Exception $e ) {
return $e->to_html();
}
+128
View File
@@ -0,0 +1,128 @@
<?php
abstract class WPStrava_Auth {
protected $auth_url = 'https://www.strava.com/oauth/authorize?response_type=code';
protected $feedback = '';
/**
* Factory method to get the correct Auth class based on specified string
* or by the options setting.
*
* @param string $auth 'refresh' or 'forever' (default 'refresh').
* @return WPStrava_Auth Instance of Auth
* @author Justin Foell <justin@foell.org>
*/
public static function get_auth( $auth = 'refresh' ) {
if ( 'forever' === $auth ) {
return new WPStrava_AuthForever();
}
// Default to refresh.
return new WPStrava_AuthRefresh();
}
abstract protected function get_authorize_url( $client_id );
public function hook() {
if ( is_admin() ) {
add_filter( 'pre_set_transient_settings_errors', array( $this, 'maybe_oauth' ) );
add_action( 'admin_init', array( $this, 'init' ) );
}
}
/**
* This runs after options are saved
*/
public function maybe_oauth( $value ) {
$settings = WPStrava::get_instance()->settings;
// User is clearing to start-over, don't oauth, ignore other errors.
if ( isset( $_POST['strava_id'] ) && $settings->ids_empty( $_POST['strava_id'] ) ) {
return array();
}
// Redirect only if all the right options are in place.
if ( $settings->is_settings_updated( $value ) && $settings->is_option_page() ) {
// Only re-auth if client ID and secret were saved.
if ( ! empty( $_POST['strava_client_id'] ) && ! empty( $_POST['strava_client_secret'] ) ) {
wp_redirect( $this->get_authorize_url( $_POST['strava_client_id'] ) );
exit();
}
}
return $value;
}
public function init() {
$settings = WPStrava::get_instance()->settings;
//only update when redirected back from strava
if ( ! isset( $_GET['settings-updated'] ) && $settings->is_settings_page() ) {
if ( isset( $_GET['code'] ) ) {
$info = $this->token_exchange_initial( $_GET['code'] );
if ( isset( $info->access_token ) ) {
// Translators: New strava token
add_settings_error( 'strava_token', 'strava_token', sprintf( __( 'New Strava token retrieved. %s', 'wp-strava' ), $this->feedback ), 'updated' );
} else {
// throw new WPStrava_Exception( '' );
add_settings_error( 'strava_token', 'strava_token', $this->feedback );
}
} 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'] ) ) );
}
}
}
protected function get_redirect_param() {
$page_name = WPStrava::get_instance()->settings->get_page_name();
return rawurlencode( admin_url( "options-general.php?page={$page_name}" ) );
}
// was fetch_token();
private function token_exchange_initial( $code ) {
$settings = WPStrava::get_instance()->settings;
$client_id = $settings->client_id;
$client_secret = $settings->client_secret;
$settings->delete_id_secret();
if ( $client_id && $client_secret ) {
$data = array(
'client_id' => $client_id,
'client_secret' => $client_secret,
'code' => $code,
);
$data = $this->add_initial_params( $data );
$strava_info = $this->token_request( $data );
if ( isset( $strava_info->access_token ) ) {
$settings->add_id( $client_id );
$settings->save_info( $client_id, $client_secret, $strava_info );
$this->feedback .= __( 'Successfully authenticated.', 'wp-strava' );
return $strava_info;
}
// Translators: error message from Strava
$this->feedback .= sprintf( __( 'There was an error receiving data from Strava: <pre>%s</pre>', 'wp-strava' ), print_r( $strava_info, true ) ); // phpcs:ignore -- Debug output.
return false;
}
$this->feedback .= __( 'Missing Client ID or Client Secret.', 'wp-strava' );
return false;
}
protected function token_request( $data ) {
$api = new WPStrava_API();
return $api->post( 'oauth/token', $data );
}
protected function add_initial_params( $data ) {
return $data;
}
}
+34
View File
@@ -0,0 +1,34 @@
<?php
/**
* This functionality is deprecated and will be shut down on October 15, 2019
*
* @see https://developers.strava.com/docs/oauth-updates/#migration-instructions
*/
/**
* AuthForever Class
*
* @since 2.0.0
* @see http://developers.strava.com/docs/authentication/
*/
class WPStrava_AuthForever extends WPStrava_Auth {
/**
* Authorize URL for old style forever tokens.
*
* @param int $client_id Strava API Client ID.
* @return string URL to authorize against.
* @author Justin Foell <justin@foell.org>
* @since 2.0.0
*/
protected function get_authorize_url( $client_id ) {
return add_query_arg(
array(
'client_id' => $client_id,
'redirect_uri' => $this->get_redirect_param(),
'approval_prompt' => 'force',
),
$this->auth_url
);
}
}
+125
View File
@@ -0,0 +1,125 @@
<?php
/**
* AuthRefresh class
*
* @since 2.0.0
* @see http://developers.strava.com/docs/authentication/
*/
class WPStrava_AuthRefresh extends WPStrava_Auth {
/**
* Hooks.
*
* @author Justin Foell <justin@foell.org>
* @since 2.0.0
*/
public function hook() {
parent::hook();
// Refresh tokens via cronjob.
add_action( 'init', array( $this, 'setup_auth_refresh_cron' ) );
add_action( 'wp_strava_auth_refresh_cron', array( $this, 'auth_refresh' ) );
}
/**
* Set up cron to refresh the auth token hourly (expires after 6-hours).
*
* @author Justin Foell <justin@foell.org>
* @since 2.0.0
*/
public function setup_auth_refresh_cron() {
// Schedule the cron job to purge all expired transients.
if ( ! wp_next_scheduled( 'wp_strava_auth_refresh_cron' ) ) {
wp_schedule_event( time(), 'hourly', 'wp_strava_auth_refresh_cron' );
}
}
/**
* Cron method to refresh auth tokens from Strava.
*
* @author Justin Foell
* @since 2.0.0
*/
public function auth_refresh() {
$settings = WPStrava::get_instance()->settings;
foreach ( $settings->info as $client_id => $info ) {
if ( ! empty( $info->refresh_token ) ) {
$this->token_exchange_refresh( $client_id, $info );
}
}
}
/**
* Authorize URL for new style refresh token auth.
*
* @param int $client_id Strava API Client ID.
* @return string URL to authorize against.
* @author Justin Foell <justin@foell.org>
* @since 2.0.0
*/
protected function get_authorize_url( $client_id ) {
return add_query_arg(
array(
'client_id' => $client_id,
'redirect_uri' => $this->get_redirect_param(),
'approval_prompt' => 'auto',
'scope' => 'activity:read,read',
),
$this->auth_url
);
}
/**
* Add 'authorization_code' grand type to first API request (when authenticating a new user).
*
* @param array $data Request array for the Strava API.
* @return array Data array with 'grant_type' => 'authorization_code' added.
* @author Justin Foell <justin@foell.org>
* @since 2.0.0
*/
protected function add_initial_params( $data ) {
$data['grant_type'] = 'authorization_code';
return $data;
}
/**
* Extend access by contacting strava with a refresh token.
*
* @param int $client_id
* @param stdClass $info
* @return boolean True if refreshed successfully, false otherwise.
* @author Justin Foell <justin@foell.org>
* @since 2.0.0
*/
protected function token_exchange_refresh( $client_id, $info ) {
$data = array(
'client_id' => $client_id,
'client_secret' => $info->client_secret,
'refresh_token' => $info->refresh_token,
'grant_type' => 'refresh_token',
);
$strava_info = $this->token_request( $data );
if ( isset( $strava_info->access_token ) ) {
$this->feedback .= __( 'ID %s successfully re-authenticated.', 'wp-strava' );
if ( $strava_info->access_token != $info->access_token ) {
$this->feedback .= __( 'ID %s access extended.', 'wp-strava' );
$settings = WPStrava::get_instance()->settings;
$settings->save_info( $client_id, $info->client_secret, $strava_info );
}
return true;
}
// @TODO how to determine if refresh wasn't successful?
$this->feedback .= sprintf( __( 'There was an error receiving data from Strava: <pre>%s</pre>', 'wp-strava' ), print_r( $strava_info, true ) ); // phpcs:ignore -- Debug output.
return false;
}
}
@@ -4,7 +4,7 @@ class WPStrava_LatestActivities {
public static function get_activities_html( $args ) {
$defaults = array(
'athlete_token' => WPStrava::get_instance()->settings->get_default_token(),
'client_id' => WPStrava::get_instance()->settings->get_default_id(),
'strava_club_id' => null,
'quantity' => 5,
'som' => WPStrava::get_instance()->settings->som,
@@ -12,12 +12,17 @@ class WPStrava_LatestActivities {
$args = wp_parse_args( $args, $defaults );
if ( isset( $args['athlete_token'] ) ) {
// Translators: Message shown when using deprecated athlete_token parameter.
return __( 'The <code>athlete_token</code> parameter is deprecated as of version 2 and should be replaced with <code>client_id</code>.', 'wp-strava' );
}
$som = WPStrava_SOM::get_som( $args['som'] );
$strava_activity = WPStrava::get_instance()->activity;
$activities = array();
try {
$activities = $strava_activity->get_activities( $args['athlete_token'], $args['strava_club_id'], $args['quantity'] );
$activities = $strava_activity->get_activities( $args['client_id'], $args['strava_club_id'], $args['quantity'] );
} catch ( WPStrava_Exception $e ) {
return $e->to_html();
}
@@ -35,7 +35,7 @@ class WPStrava_LatestActivitiesShortcode {
/**
* Shortcode handler for [activities].
*
* [activities som=metric quantity=5 athlete_token=xxx|strava_club_id=yyy]
* [activities som=metric quantity=5 client_id=xxx|strava_club_id=yyy]
*
* @param array $atts Array of attributes (id, som, etc.).
* @return string Shortcode output
@@ -25,7 +25,7 @@ class WPStrava_LatestActivitiesWidget extends WP_Widget {
$title = apply_filters( 'widget_title', empty( $instance['title'] ) ? __( 'Latest Activities', 'wp-strava' ) : $instance['title'] );
$activities_args = array(
'athlete_token' => isset( $instance['athlete_token'] ) ? $instance['athlete_token'] : null,
'client_id' => isset( $instance['client_id'] ) ? $instance['client_id'] : null,
'strava_club_id' => isset( $instance['strava_club_id'] ) ? $instance['strava_club_id'] : null,
'quantity' => isset( $instance['quantity'] ) ? $instance['quantity'] : null,
);
@@ -42,7 +42,7 @@ class WPStrava_LatestActivitiesWidget extends WP_Widget {
public function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance['title'] = strip_tags( $new_instance['title'] );
$instance['athlete_token'] = strip_tags( $new_instance['athlete_token'] );
$instance['client_id'] = strip_tags( $new_instance['client_id'] );
$instance['strava_club_id'] = strip_tags( $new_instance['strava_club_id'] );
$instance['quantity'] = $new_instance['quantity'];
@@ -52,8 +52,8 @@ class WPStrava_LatestActivitiesWidget extends WP_Widget {
/** @see WP_Widget::form */
public function form( $instance ) {
$title = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : __( 'Latest Activities', '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();
$all_ids = WPStrava::get_instance()->settings->get_all_ids();
$client_id = isset( $instance['client_id'] ) ? esc_attr( $instance['client_id'] ) : WPStrava::get_instance()->settings->get_default_id();
$strava_club_id = isset( $instance['strava_club_id'] ) ? esc_attr( $instance['strava_club_id'] ) : '';
$quantity = isset( $instance['quantity'] ) ? absint( $instance['quantity'] ) : 5;
@@ -63,10 +63,10 @@ class WPStrava_LatestActivitiesWidget extends WP_Widget {
<input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo $title; ?>" />
</p>
<p>
<label for="<?php echo $this->get_field_id( 'athlete_token' ); ?>"><?php _e( 'Athlete:', 'wp-strava' ); ?></label>
<select name="<?php echo $this->get_field_name( 'athlete_token' ); ?>">
<?php foreach ( $all_tokens as $token => $nickname ) : ?>
<option value="<?php echo $token; ?>"<?php selected( $token, $athlete_token ); ?>><?php echo $nickname; ?></option>
<label for="<?php echo $this->get_field_id( 'client_id' ); ?>"><?php _e( 'Athlete:', 'wp-strava' ); ?></label>
<select name="<?php echo $this->get_field_name( 'client_id' ); ?>">
<?php foreach ( $all_ids as $id => $nickname ) : ?>
<option value="<?php echo $id; ?>"<?php selected( $id, $client_id ); ?>><?php echo $nickname; ?></option>
<?php endforeach; ?>
</select>
</p>
@@ -17,8 +17,8 @@ class WPStrava_LatestMapWidget extends WP_Widget {
public function form( $instance ) {
// outputs the options form on admin
$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();
$all_ids = WPStrava::get_instance()->settings->get_all_ids();
$client_id = isset( $instance['client_id'] ) ? esc_attr( $instance['client_id'] ) : WPStrava::get_instance()->settings->get_default_id();
$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'] ) : '';
@@ -31,10 +31,10 @@ class WPStrava_LatestMapWidget extends WP_Widget {
<input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo $title; ?>" />
</p>
<p>
<label for="<?php echo $this->get_field_id( 'athlete_token' ); ?>"><?php _e( 'Athlete:', 'wp-strava' ); ?></label>
<select name="<?php echo $this->get_field_name( 'athlete_token' ); ?>">
<?php foreach ( $all_tokens as $token => $nickname ) : ?>
<option value="<?php echo $token; ?>"<?php selected( $token, $athlete_token ); ?>><?php echo $nickname; ?></option>
<label for="<?php echo $this->get_field_id( 'client_id' ); ?>"><?php _e( 'Athlete:', 'wp-strava' ); ?></label>
<select name="<?php echo $this->get_field_name( 'client_id' ); ?>">
<?php foreach ( $all_ids as $id => $nickname ) : ?>
<option value="<?php echo $id; ?>"<?php selected( $id, $client_id ); ?>><?php echo $nickname; ?></option>
<?php endforeach; ?>
</select>
</p>
@@ -56,7 +56,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['client_id'] = strip_tags( $new_instance['client_id'] );
$instance['strava_club_id'] = strip_tags( $new_instance['strava_club_id'] );
$instance['distance_min'] = strip_tags( $new_instance['distance_min'] );
return $instance;
@@ -71,12 +71,12 @@ class WPStrava_LatestMapWidget extends WP_Widget {
public function widget( $args, $instance ) {
$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();
$client_id = isset( $instance['client_id'] ) ? $instance['client_id'] : WPStrava::get_instance()->settings->get_default_id();
$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;
$id = empty( $strava_club_id ) ? $athlete_token : $strava_club_id;
$id = empty( $strava_club_id ) ? $client_id : $strava_club_id;
// Try our transient first.
$activity_transient = get_transient( 'strava_latest_map_activity_' . $id );
@@ -95,7 +95,7 @@ class WPStrava_LatestMapWidget extends WP_Widget {
$activities = array();
try {
$activities = $strava_activity->get_activities( $athlete_token, $strava_club_id );
$activities = $strava_activity->get_activities( $client_id, $strava_club_id );
} catch ( WPStrava_Exception $e ) {
echo $e->to_html();
}
@@ -47,17 +47,22 @@ class WPStrava_RouteShortcode {
$this->add_script = true;
$defaults = array(
'id' => 0,
'som' => WPStrava::get_instance()->settings->som,
'map_width' => '480',
'map_height' => '320',
'athlete_token' => WPStrava::get_instance()->settings->get_default_token(),
'markers' => false,
'image_only' => false,
'id' => 0,
'som' => WPStrava::get_instance()->settings->som,
'map_width' => '480',
'map_height' => '320',
'client_id' => WPStrava::get_instance()->settings->get_default_id(),
'markers' => false,
'image_only' => false,
);
$atts = shortcode_atts( $defaults, $atts, 'route' );
if ( isset( $atts['athlete_token'] ) ) {
// Translators: Message shown when using deprecated athlete_token parameter.
return __( 'The <code>athlete_token</code> parameter is deprecated as of version 2 and should be replaced with <code>client_id</code>.', 'wp-strava' );
}
/* Make sure boolean values are actually boolean
* @see https://wordpress.stackexchange.com/a/119299
*/
@@ -11,12 +11,22 @@
class WPStrava_Settings {
private $feedback;
private $tokens = array();
private $ids = array();
private $page_name = 'wp-strava-options';
private $option_page = 'wp-strava-settings-group';
private $adding_athlete = true;
/**
* Settings constructor.
*
* @author Justin Foell <justin@foell.org>
* @since 2.0
*/
public function __construct() {
$this->ids = $this->get_ids();
}
/**
* Register actions & filters for menus and authentication.
*
@@ -26,43 +36,11 @@ class WPStrava_Settings {
public function hook() {
add_action( 'admin_init', array( $this, 'register_strava_settings' ) );
add_action( 'admin_menu', array( $this, 'add_strava_menu' ) );
add_filter( 'pre_set_transient_settings_errors', array( $this, 'maybe_oauth' ) );
add_filter( 'plugin_action_links_' . WPSTRAVA_PLUGIN_NAME, array( $this, 'settings_link' ) );
add_action( 'in_plugin_update_message-wp-strava/wp-strava.php', array( $this, 'plugin_update_message' ), 10, 2 );
add_action( 'after_plugin_row_wp-strava/wp-strava.php', array( $this, 'ms_plugin_update_message' ), 10, 2 );
}
/**
* Run the OAuth process after options are saved.
*
* @author Justin Foell <justin@foell.org>
* @since 1.0
*/
public function maybe_oauth( $value ) {
// User is clearing to start-over, don't oauth, ignore other errors.
if ( isset( $_POST['strava_token'] ) && $this->tokens_empty( $_POST['strava_token'] ) ) {
return array();
}
// Redirect only if all the right options are in place.
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.
// Only re-auth if client ID and secret were saved.
if ( ! empty( $_POST['strava_client_id'] ) && ! empty( $_POST['strava_client_secret'] ) ) {
$client_id = $_POST['strava_client_id'];
$client_secret = $_POST['strava_client_secret'];
$redirect = rawurlencode( 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();
}
}
}
return $value;
}
/**
* Add the strava settings menu.
*
@@ -79,37 +57,6 @@ class WPStrava_Settings {
);
}
/**
* Initialize the settings by getting tokens.
*
* @author Justin Foell <justin@foell.org>
* @since 1.0
*/
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->fetch_token( $_GET['code'] );
if ( $token ) {
// Translators: strava token
add_settings_error( 'strava_token', 'strava_token', sprintf( __( 'New Strava token retrieved. %s', 'wp-strava' ), $this->feedback ), 'updated' );
$this->add_token( $token );
update_option( 'strava_token', $this->tokens );
} else {
add_settings_error( 'strava_token', 'strava_token', $this->feedback );
}
} 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'] ) ) );
}
}
}
/**
* Register settings using the WP Settings API.
*
@@ -117,11 +64,11 @@ class WPStrava_Settings {
* @since 0.62
*/
public function register_strava_settings() {
$this->init();
add_settings_section( 'strava_api', __( 'Strava API', 'wp-strava' ), array( $this, 'print_api_instructions' ), 'wp-strava' );
if ( $this->tokens_empty( $this->tokens ) ) {
$this->adding_athlete = $this->is_adding_athlete();
if ( $this->ids_empty( $this->ids ) ) {
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' ) );
@@ -130,8 +77,8 @@ class WPStrava_Settings {
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' );
register_setting( $this->option_page, 'strava_id', array( $this, 'sanitize_id' ) );
add_settings_field( 'strava_id', __( 'Saved ID', 'wp-strava' ), array( $this, 'print_id_input' ), 'wp-strava', 'strava_api' );
// Add additional fields
register_setting( $this->option_page, 'strava_client_id', array( $this, 'sanitize_client_id' ) );
@@ -172,7 +119,6 @@ class WPStrava_Settings {
* @since 0.62
*/
public function print_api_instructions() {
$signup_url = 'http://www.strava.com/developers';
$settings_url = 'https://www.strava.com/settings/api';
$icon_url = 'https://plugins.svn.wordpress.org/wp-strava/assets/icon-128x128.png';
$blog_name = get_bloginfo( 'name' );
@@ -196,8 +142,8 @@ class WPStrava_Settings {
<li>Authorization Callback Domain: <strong>%7\$s</strong></li>
</ul>
<li>Once you've created your API Application at strava.com, enter the <strong>Client ID</strong> and <strong>Client Secret</strong> below, which can now be found on that same strava API Settings page.
<li>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.</li>
<li>If you need to re-authorize your API Application, erase your Strava Token here and click 'Save Changes' to start over.</li>
<li>After saving your Client ID and Secret, you'll be redirected to strava to authorize your API Application. If successful, your Strava ID will display in a table, next to your nickname.</li>
<li>If you need to re-authorize your API Application, erase your Strava ID next to your nickname and click 'Save Changes' to start over.</li>
</ol>", 'wp-strava' ),
$settings_url,
$settings_url,
@@ -222,7 +168,6 @@ class WPStrava_Settings {
<li>To use Google map images, you must create a Static Maps API Key. Create a free key by going here: <a href='%1\$s'>%2\$s</a> and clicking <strong>Get a Key</strong></li>
<li>Once you've created your Google Static Maps API Key, enter the key below.
</ol>", 'wp-strava' ), $maps_url, $maps_url );
}
/**
@@ -232,21 +177,7 @@ class WPStrava_Settings {
* @since 0.62
*/
public function print_strava_options() {
?>
<div class="wrap">
<div id="icon-options-general" class="icon32"><br/></div>
<h2><?php esc_html_e( 'Strava Settings', 'wp-strava' ); ?></h2>
<form method="post" action="<?php echo admin_url( 'options.php' ); ?>">
<?php settings_fields( $this->option_page ); ?>
<?php do_settings_sections( 'wp-strava' ); ?>
<p class="submit">
<input type="submit" class="button-primary" value="<?php esc_html_e( 'Save Changes', 'wp-strava' ); ?>" />
</p>
</form>
</div>
<?php
include WPSTRAVA_PLUGIN_DIR . 'templates/admin-settings.php';
}
/**
@@ -280,23 +211,25 @@ class WPStrava_Settings {
* @since 1.2.0
*/
public function print_nickname_input() {
$nickname = $this->tokens_empty( $this->tokens ) ? __( 'Default', 'wp-strava' ) : '';
$nickname = $this->ids_empty( $this->ids ) ? __( 'Default', 'wp-strava' ) : '';
?>
<input type="text" name="strava_nickname[]" value="<?php echo $nickname; ?>" />
<?php
}
/**
* Print the strava token(s)
* Print the strava ID(s).
*
* Renamed from print_token_input().
*
* @author Justin Foell <justin@foell.org>
* @since 0.62
* @since 2.0
*/
public function print_token_input() {
foreach ( $this->get_all_tokens() as $token => $nickname ) {
public function print_id_input() {
foreach ( $this->get_all_ids() as $id => $nickname ) {
?>
<input type="text" name="strava_token[]" value="<?php echo $token; ?>" />
<input type="text" name="strava_nickname[]" value="<?php echo $nickname; ?>" />
<input type="text" name="strava_id[]" value="<?php echo esc_attr( $id ); ?>" />
<input type="text" name="strava_nickname[]" value="<?php echo esc_attr( $nickname ); ?>" />
<br/>
<?php
}
@@ -353,13 +286,13 @@ class WPStrava_Settings {
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'] ) );
// Chop $nicknames to same size as ids.
$nicknames = array_slice( $nicknames, 0, count( $_POST['strava_id'] ) );
// Remove indexes from $nicknames that have empty tokens.
foreach ( $_POST['strava_token'] as $index => $token ) {
$token = trim( $token );
if ( empty( $token ) ) {
// Remove indexes from $nicknames that have empty ids.
foreach ( $_POST['strava_id'] as $index => $id ) {
$id = trim( $id );
if ( empty( $id ) ) {
unset( $nicknames[ $index ] );
}
}
@@ -378,55 +311,17 @@ class WPStrava_Settings {
}
/**
* Sanitize the token.
* Sanitize the ID.
*
* Renamed from sanitize_token().
*
* @param string $token
* @return string
* @author Justin Foell <justin@foell.org>
* @since 0.62
* @since 2.0
*/
public function sanitize_token( $token ) {
return $token;
}
/**
* Fetch the access token from Strava - previously get_token()
*
* @param string $code
* @return mixed Boolean false if there was a problem, token string otherwise.
* @author Justin Foell <justin@foell.org>
* @since 1.0
*/
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 ) {
$api = new WPStrava_API();
$data = array(
'client_id' => $client_id,
'client_secret' => $client_secret,
'code' => $code,
);
$strava_info = $api->post( 'oauth/token', $data );
if ( isset( $strava_info->access_token ) ) {
$this->feedback .= __( 'Successfully authenticated.', 'wp-strava' );
return $strava_info->access_token;
}
// Translators: error message from Strava
$this->feedback .= sprintf( __( 'There was an error receiving data from Strava: <pre>%s</pre>', 'wp-strava' ), print_r( $strava_info, true ) ); // phpcs:ignore -- Debug output.
return false;
}
$this->feedback .= __( 'Missing Client ID or Client Secret.', 'wp-strava' );
return false;
public function sanitize_id( $id ) {
return $id;
}
/**
@@ -561,61 +456,63 @@ class WPStrava_Settings {
$wpdb->query( "DELETE FROM {$wpdb->options} WHERE `option_name` LIKE '_transient_timeout_strava_latest_map_%'" );
$wpdb->query( "DELETE FROM {$wpdb->options} WHERE `option_name` LIKE '_transient_strava_latest_map_%'" );
$wpdb->query( "DELETE FROM {$wpdb->options} WHERE `option_name` LIKE 'strava_latest_map%'" );
delete_option( 'strava_token' );
}
return null;
}
/**
* Gets all saved strava tokens as an array.
* Gets all saved strava ids as an array.
*
* @return array
* @author Justin Foell <justin@foell.org>
* @since 1.2.0
* @since 2.0.0
*/
public function get_tokens() {
$tokens = get_option( 'strava_token' );
if ( ! is_array( $tokens ) ) {
$tokens = array( $tokens );
public function get_ids() {
$ids = get_option( 'strava_id' );
if ( ! is_array( $ids ) ) {
$ids = array( $ids );
}
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
foreach ( $ids as $index => $id ) {
if ( empty( $id ) ) {
unset( $ids[ $index ] );
$ids = array_values( $ids ); // Rebase array keys after unset @see https://stackoverflow.com/a/5943165/2146022
}
}
return $tokens;
return $ids;
}
/**
* Returns first (default) token saved.
* Returns first (default) ID saved.
*
* @return string|null
* @author Justin Foell <justin@foell.org>
* @since 1.2.0
*/
public function get_default_token() {
$tokens = $this->get_tokens();
return isset( $tokens[0] ) ? $tokens[0] : null;
public function get_default_id() {
$ids = $this->get_ids();
return isset( $ids[0] ) ? $ids[0] : null;
}
/**
* Get all tokens and their nicknames in one array.
* Get all IDs and their nicknames in one array.
*
* @return void
* @author Justin Foell <justin@foell.org>
* @since 1.2.0
* @since 2.0.0
*/
public function get_all_tokens() {
$tokens = $this->get_tokens();
public function get_all_ids() {
$ids = $this->get_ids();
$nicknames = $this->nickname;
$all = array();
$number = 1;
foreach ( $tokens as $index => $token ) {
foreach ( $ids as $index => $id ) {
if ( ! empty( $nicknames[ $index ] ) ) {
$all[ $token ] = $nicknames[ $index ];
$all[ $id ] = $nicknames[ $index ];
} else {
$all[ $token ] = $this->get_default_nickname( $number );
$all[ $id ] = $this->get_default_nickname( $number );
}
$number++;
}
@@ -637,22 +534,22 @@ class WPStrava_Settings {
}
/**
* Checks for valid tokens.
* Checks for valid IDs.
*
* @author Justin Foell <justin@foell.org>
* @since 1.2.0
*
* @param string|array Single token or array of tokens.
* @param string|array Single ID or array of IDs.
* @return boolean True if empty.
*/
public function tokens_empty( $tokens ) {
if ( empty( $tokens ) ) {
public function ids_empty( $ids ) {
if ( empty( $ids ) ) {
return true;
}
if ( is_array( $tokens ) ) {
foreach ( $tokens as $token ) {
if ( ! empty( $token ) ) {
if ( is_array( $ids ) ) {
foreach ( $ids as $id ) {
if ( ! empty( $id ) ) {
return false;
}
}
@@ -662,19 +559,120 @@ class WPStrava_Settings {
}
/**
* Only add a token if it's not already there.
* Add an ID if it's not already there, and save to the DB.
*
* @param string $token
* @param string $id
*
* @author Justin Foell <justin@foell.org>
* @since 1.2.0
* @since 2.0.0
*/
public function add_token( $token ) {
if ( false === array_search( $token, $this->tokens, true ) ) {
$this->tokens[] = $token;
public function add_id( $id ) {
if ( false === array_search( $id, $this->ids, true ) ) {
$this->ids[] = $id;
update_option( 'strava_id', $this->ids );
}
}
/**
* Undocumented function
*
* @param int $id Strava API Client ID
* @param string $secret Strava API Client Secret
* @param stdClass $info
* @author Justin Foell <justin.foell@webdevstudios.com>
* @since 2.0.0
*/
public function save_info( $id, $secret, $info ) {
$infos = get_option( 'strava_info', array() );
$infos = array_filter( $infos, array( $this, 'filter_by_id' ), ARRAY_FILTER_USE_KEY ); // Remove old IDs.
$info->client_secret = $secret;
$infos[ $id ] = $info;
update_option( 'strava_info', $infos );
}
/**
* array_filter() callback to remove info for IDs we no longer have.
*
* @param int $key Strava Client ID
* @return boolean True if Client ID is in $this->ids, false otherwise.
* @author Justin Foell <justin.foell@webdevstudios.com>
* @since 2.0.0
*/
public function filter_by_id( $key ) {
if ( in_array( $key, $this->ids ) ) {
return true;
}
return false;
}
/**
* Undocumented function
*
* @return void
* @author Justin Foell <justin.foell@webdevstudios.com>
* @since 2.0.0
*/
public function delete_id_secret() {
delete_option( 'strava_client_id' );
delete_option( 'strava_client_secret' );
}
/**
* Undocumented function
*
* @param [type] $value
* @return boolean
* @author Justin Foell <justin.foell@webdevstudios.com>
* @since 2.0.0
*/
public function is_settings_updated( $value ) {
return isset( $value[0]['type'] ) && 'updated' === $value[0]['type'];
}
/**
* Undocumented function
*
* @return boolean
* @author Justin Foell <justin.foell@webdevstudios.com>
* @since 2.0.0
*/
public function is_option_page() {
return isset( $_POST['option_page'] ) && $_POST['option_page'] === $this->option_page;
}
/**
* Undocumented function
*
* @return boolean
* @author Justin Foell <justin.foell@webdevstudios.com>
* @since 2.0.0
*/
public function is_settings_page() {
return isset( $_GET['page'] ) && $_GET['page'] === $this->page_name;
}
/**
* Undocumented function
*
* @return string
* @author Justin Foell <justin.foell@webdevstudios.com>
* @since 2.0.0
*/
public function get_page_name() {
return $this->page_name;
}
/**
* Undocumented function
*
* @return boolean
* @author Justin Foell <justin.foell@webdevstudios.com>
* @since 2.0.0
*/
private function is_adding_athlete() {
return ! ( empty( $_POST['strava_client_id'] ) && empty( $_POST['strava_client_secret'] ) );
}
/**
* Getter for Strava settings in wp_options.
*
@@ -66,7 +66,7 @@ class WPStrava_StaticMap {
* }
*/
private static function decode_start_finish( $enc ) {
require_once WPSTRAVA_PLUGIN_DIR . 'lib/Polyline.php';
require_once WPSTRAVA_PLUGIN_DIR . 'includes/Polyline.php';
$points = Polyline::decode( $enc );
$points = Polyline::pair( $points );
$start = $points[0];
+1 -1
View File
@@ -16,7 +16,7 @@ function wpstrava_autoload_classes( $class_name ) {
}
// @TODO Add directory searching if they get created.
$file = WPSTRAVA_PLUGIN_DIR . '/lib/' . implode( '/', $parts ) . '.php';
$file = WPSTRAVA_PLUGIN_DIR . '/includes/' . implode( '/', $parts ) . '.php';
if ( file_exists( $file ) ) {
include_once $file;
}
+2
View File
@@ -0,0 +1,2 @@
<?php
+1 -1
View File
@@ -8,7 +8,7 @@
<exclude name="WordPress.Files.FileName.InvalidClassFileName" />
</rule>
<file>./lib</file>
<file>./includes</file>
<file>./wp-strava.php</file>
<exclude-pattern>*/vendor/*</exclude-pattern>
+1 -1
View File
@@ -16,7 +16,7 @@
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">lib</directory>
<directory suffix=".php">includes</directory>
</whitelist>
</filter>
</phpunit>
+24 -8
View File
@@ -4,13 +4,12 @@ Contributors: cmanon, jrfoell, lancewillett, dlintott, sebastianerb
Tags: strava, activity, bicycle, cycling, biking, running, run, swimming, swim, paddle, kayak, gps, shortcode, widget, plugin
Requires at least: 4.6
Tested up to: 5.1
Stable tag: 1.7.3
Stable tag: 2.0
Requires PHP: 5.2
License: GPLv2 or later
Show your Strava activity on your WordPress site.
== Description ==
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.
@@ -32,7 +31,7 @@ Also takes the following optional parameters:
* som - english/metric (system of measure - override from default setting).
* map_width - width (width of image in pixels). Note both width and height parameters are limited to 640px except on premium API plans: https://developers.google.com/maps/documentation/maps-static/dev-guide#Imagesizes
* map_height - height (height of image in pixels). See note above on max height.
* 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).
* client_id - 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).
* markers - Display markers at the start/finish point (true/false, defaults to false).
* image_only - Display only the map image and not the table (true/false, defaults to false).
@@ -48,7 +47,7 @@ This also takes the same optional parameters as the [activity] shortcode above.
* som - english/metric (system of measure - override from default setting).
* quantity - number of activities to show.
* 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).
* client_id - 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).
* strava_club_id - Will display activity from the specified Strava club ID instead of an athlete.
@@ -58,20 +57,24 @@ 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.
== Frequently Asked Questions ==
= Why am I getting "ERROR 401 Unauthorized"? =
When you have multiple athletes saved, the first is considered to be the default athlete. If you use a shortcode to display activity from anyone other than the default athlete, you must add the athlete token (found on the wp-strava settings page) to the shortcode, such as athlete_token=c764a2b199cff281e39f24671760c1b9c9fe005e. If you've recently had to re-authorize with Strava, your athlete token may have changed and will need to be updated in your shortcodes and widgets. For widgets, re-select the athlete you'd like to display and click Save.
When you have multiple athletes saved, the first is considered to be the default athlete. If you use a shortcode to display activity from anyone other than the default athlete, you must add the athlete token (found on the wp-strava settings page) to the shortcode, such as client_id=17791. If you've recently had to re-authorize with Strava, your athlete token may have changed and will need to be updated in your shortcodes and widgets. For widgets, re-select the athlete you'd like to display and click Save.
= Why is my Google Map not showing up? =
If your API key works with other Google Maps plugins but not WP Strava, you may need to enable the "Static Maps" functionality on your google account. This is especially true for people using G Suite accounts (not just a @gmail.com address). While logged into your G Suite email, visit https://console.developers.google.com/apis/library/static-maps-backend.googleapis.com/?q=static and make sure the "Static Maps API" is enabled. For more details see https://wordpress.org/support/topic/no-data-errors/
= I recently uploaded an activity, why is it not showing on my site? =
WP-Strava caches activity for one hour so your site doesn't hit the Strava API on every page load. If you recently uploaded activity and want to see it right away, go to the Settings -> Strava in the wp-admin dashboard, check the checkbox labeled "Clear cache (images & transient data)" and then click Save Changes.
== Screenshots ==
1. WP Strava settings - this walks you through connecting the WP Strava plugin to your strava account. You can connect multiple accounts by authenticating each one here. Add your Google Maps key for map display here. You can also set the system of measurement (miles/kilometers) and clear any saved data.
@@ -80,18 +83,25 @@ WP-Strava caches activity for one hour so your site doesn't hit the Strava API o
4. Latest Map Widget - shows a map of your most recent activity.
5. Latest Map Widget Settings - settings for the Latest Map Widget. You can limit your activity by minimum distance to show only longer efforts.
6. Activity Shortcode - Shows a map of activity with some statistics.
7. Activity Shortcode Settings - An example activity shortcode. The athlete_token parameter is only needed if your site is connected to multiple athlete accounts.
7. Activity Shortcode Settings - An example activity shortcode. The client_id parameter is only needed if your site is connected to multiple athlete accounts.
8. Route Shortcode - Shows a map of a route.
9. Route Shortcode Settings - An example route shortcode. Add markers=true to show green/red start/stop points.
10. Activities Shortcode - Shows latest athlete activity in a page or post.
11. Activities Shortcode Settings - An example activities shortcode. The athlete_token parameter is only needed if your site is connected to multiple athlete accounts.
11. Activities Shortcode Settings - An example activities shortcode. The client_id parameter is only needed if your site is connected to multiple athlete accounts.
== Changelog ==
= 2.0.0 =
Added new Strava "refresh tokens" ala https://developers.strava.com/docs/oauth-updates/#migration-instructions
= 1.7.3 =
Added update notice.
= 1.7.2 =
Added setting to hide elevation.
@@ -106,6 +116,7 @@ Fixed swimpace calculation.
Fixed seconds display on pace.
Added Hide Activity Time option to hide time display from Latest Activities List.
= 1.7.0 =
Added Sebastian Erb to contributors.
@@ -235,6 +246,11 @@ Initial version.
== Upgrade Notice ==
= 2.0 =
Version 2.0 is mandatory after October 15th, 2019. 2.0 settings upgrade instructions: <a href="https://github.com/cmanon/wp-strava/wiki/2.0-Upgrade">https://github.com/cmanon/wp-strava/wiki/2.0-Upgrade</a>.
= 1.7.3 =
Version 2.0 will be mandatory after October 15th, 2019. Try the 2.0 beta: <a href="https://github.com/cmanon/wp-strava/releases">https://github.com/cmanon/wp-strava/releases</a>. 2.0 settings upgrade instructions: <a href="https://github.com/cmanon/wp-strava/wiki/2.0-Upgrade">https://github.com/cmanon/wp-strava/wiki/2.0-Upgrade</a>.
Version 2.0 is mandatory after October 15th, 2019. Try the 2.0 beta: <a href="https://github.com/cmanon/wp-strava/releases">https://github.com/cmanon/wp-strava/releases</a>. 2.0 settings upgrade instructions: <a href="https://github.com/cmanon/wp-strava/wiki/2.0-Upgrade">https://github.com/cmanon/wp-strava/wiki/2.0-Upgrade</a>.
+13
View File
@@ -0,0 +1,13 @@
<div class="wrap">
<div id="icon-options-general" class="icon32"><br/></div>
<h2><?php esc_html_e( 'Strava Settings', 'wp-strava' ); ?></h2>
<form method="post" action="<?php echo admin_url( 'options.php' ); ?>">
<?php settings_fields( $this->option_page ); ?>
<?php do_settings_sections( 'wp-strava' ); ?>
<p class="submit">
<input type="submit" class="button-primary" value="<?php esc_html_e( 'Save Changes', 'wp-strava' ); ?>" />
</p>
</form>
</div>
+1 -1
View File
@@ -4,7 +4,7 @@ if ( ! defined( 'WPSTRAVA_PLUGIN_DIR' ) ) {
define( 'WPSTRAVA_PLUGIN_DIR', dirname( __FILE__ ) . '/../' );
}
require_once dirname( __FILE__ ) . '/../lib/autoload.php';
require_once dirname( __FILE__ ) . '/../includes/autoload.php';
require_once dirname( __FILE__ ) . '/../vendor/autoload.php';
WP_Mock::bootstrap();
-7
View File
@@ -1,7 +0,0 @@
<?php
// autoload.php @generated by Composer
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit270e8bb56ffe1d33754fb3c59cf60d66::getLoader();
+2 -2
View File
@@ -3,7 +3,7 @@
* Plugin Name: WP Strava
* Plugin URI: https://wordpress.org/plugins/wp-strava/
* Description: Show your strava.com activity on your WordPress site. Some Icons are Copyright © Yusuke Kamiyamane. All rights reserved. Licensed under a Creative Commons Attribution 3.0 license.
* Version: 1.7.3
* Version: 2.0b1
* Author: Carlos Santa Cruz, Justin Foell, Lance Willett, Daniel Lintott, Sebastian Erb
* License: GPL2
* Text Domain: wp-strava
@@ -35,7 +35,7 @@ if ( ! defined( 'WPSTRAVA_DEBUG' ) ) {
define( 'WPSTRAVA_DEBUG', false );
}
require_once WPSTRAVA_PLUGIN_DIR . 'lib/autoload.php';
require_once WPSTRAVA_PLUGIN_DIR . 'includes/autoload.php';
// Load the plugin and multilingual support.
function wpstrava_load_plugin_textdomain() {