diff --git a/lib/WPStrava.php b/lib/WPStrava.php index c68a999..1ee5400 100644 --- a/lib/WPStrava.php +++ b/lib/WPStrava.php @@ -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,9 +46,11 @@ class WPStrava { */ private function __construct() { $this->settings = new WPStrava_Settings(); + $this->auth = WPStrava_Auth::get_auth( 'forever' ); if ( is_admin() ) { $this->settings->hook(); + $this->auth->hook(); } else { add_action( 'init', array( $this, 'register_shortcodes' ) ); add_action( 'wp_enqueue_scripts', array( $this, 'register_scripts' ) ); @@ -90,7 +98,7 @@ 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 diff --git a/lib/WPStrava/Auth.php b/lib/WPStrava/Auth.php new file mode 100644 index 0000000..208e1e1 --- /dev/null +++ b/lib/WPStrava/Auth.php @@ -0,0 +1,119 @@ + + */ + 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() { + 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_token'] ) && $settings->tokens_empty( $_POST['strava_token'] ) ) { + 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' ); + $settings->add_token( $info->access_token ); + $settings->update_token(); + } 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, + ); + + $strava_info = $this->token_request( $data ); + + if ( isset( $strava_info->access_token ) ) { + $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:
%s', '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 ); + } + +} diff --git a/lib/WPStrava/AuthForever.php b/lib/WPStrava/AuthForever.php new file mode 100644 index 0000000..f0a2cad --- /dev/null +++ b/lib/WPStrava/AuthForever.php @@ -0,0 +1,25 @@ + $client_id, + 'redirect_uri' => $this->get_redirect_param(), + 'approval_prompt' => 'force', + ), + $this->auth_url + ); + } +} diff --git a/lib/WPStrava/AuthRefresh.php b/lib/WPStrava/AuthRefresh.php new file mode 100644 index 0000000..a2397d8 --- /dev/null +++ b/lib/WPStrava/AuthRefresh.php @@ -0,0 +1,47 @@ + $client_id, + 'redirect_uri' => $this->get_redirect_param(), + 'approval_prompt' => 'auto', + 'scope' => 'read,activity:read', + ), + $this->auth_url + ); + } + + protected function token_exchange_refresh() { + $data = array( + 'client_id' => $client_id, + 'client_secret' => $client_secret, + 'refresh_token' => $refresh_token, + 'grant_type' => 'refresh_token', + ); + + $strava_info = $this->token_request( $data ); + + if ( isset( $strava_info->access_token ) ) { + $this->feedback .= __( 'Successfully re-authenticated.', 'wp-strava' ); + return $strava_info; + } + + $this->feedback .= sprintf( __( 'There was an error receiving data from Strava:
%s', 'wp-strava' ), print_r( $strava_info, true ) ); // phpcs:ignore -- Debug output. + return false; + } + +} + diff --git a/lib/WPStrava/Settings.php b/lib/WPStrava/Settings.php index 28e0326..9ea8605 100644 --- a/lib/WPStrava/Settings.php +++ b/lib/WPStrava/Settings.php @@ -11,7 +11,6 @@ class WPStrava_Settings { - private $feedback; private $tokens = array(); private $page_name = 'wp-strava-options'; private $option_page = 'wp-strava-settings-group'; @@ -19,40 +18,11 @@ class WPStrava_Settings { //register admin menus public function hook() { - add_action( 'admin_init', array( $this, 'register_strava_settings' ) ); + add_action( 'admin_init', array( $this, 'register_strava_settings' ), 20 ); 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' ) ); } - /** - * This runs after options are saved - */ - 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; - } - public function add_strava_menu() { add_options_page( __( 'Strava Settings', 'wp-strava' ), @@ -63,36 +33,12 @@ class WPStrava_Settings { ); } - 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'] ) ) ); - } - } - } - public function register_strava_settings() { - $this->init(); - add_settings_section( 'strava_api', __( 'Strava API', 'wp-strava' ), array( $this, 'print_api_instructions' ), 'wp-strava' ); + $this->adding_athlete = $this->is_adding_athlete(); + $this->tokens = $this->get_tokens(); + 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' ) ); @@ -136,7 +82,6 @@ class WPStrava_Settings { } 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' ); @@ -180,7 +125,6 @@ class WPStrava_Settings {
%s', '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 print_gmaps_key_input() { ?> @@ -494,6 +406,78 @@ class WPStrava_Settings { } } + /** + * Undocumented function + * + * @param array $token + * @author Justin Foell