Strava PHP API Class

    Current Version: 1.0.0
    Price: FREE


    Strava has discontinued their version 1 and version 2 API’s which are referenced by the class below. Without API access this class has been rendered inoperable. It remains here for reference purposes only. Unfortunately Strava has not opened the version 3 API to public access. For more information please see this posting: http://www.schiffner.com/how-to-lose-a-developer-in-60-seconds-strava/.


    This class is designed to interface with Strava.com and retrieve rides and ride associated data via the Strava api.


    Dependancies
    PHP 5.3+
    A valid Strava.com user account


    The Class
    The class is straight forward and each method/function is documented in the source below. There are two pieces of data that are required for most operations. A Strava user id (the user id assigned by Strava when you create a Strava.com account) and a Strava Authorization Token that matches the user id (obtained using the login function included with the class). A Strava user id and authorization token can be passed during construct to minmize the amount of data passed to each method during use. Both are optional during construct. Whether or not these values are passed when creating each class instance, the values can be overridden by passing them to each individual function. A note about Strava Autorization Tokens; The tokens are persistent and do not expire. They should not be created each time you access Strava data. Rather you should obtain a Strava Authorization Token a single time and store it for future use. Although persistent, you can only have a limited number of tokens in circulation. Constantly logging into Strava will eventually invalidate older tokens.

    //#######################################################################\\
    //# Author: Christopher Schiffner                                       #\\
    //# Filename: cls.strava.php                                            #\\
    //# Copyright: Christopher Schiffner, All Rights Reserved               #\\
    //# Description: Strava PHP API Class                                   #\\
    //# Version: 1.0                                                        #\\
    //# Details: Supports all popular read-only api's                       #\\
    //#                                                                     #\\
    //# License: MIT License                                                #\\
    //#######################################################################\\
    
    class clsStrava
    {
        private $strava_userid="";
        private $strava_units="";
        private $strava_token="";
        private $strava_fetch_mode="";
    
    
    
    
        //FUNCTION: __construct
        //   Login to Strava with email/password provided during construction via restful api interface
        //
        //   Accepts
        //      $userid (optional) = ID for strava account
        //      $token (optional) = Strava authorization token. Tokens are persistent and don't expire.
        //              To obtain a strava token utilize the include login function.
        //      $units (optional) = Valid inputs: imperial, metric, "" <blank>.
        //          Units returned by ride scripts will be as follows:
        //              imperial (default): miles per hour (speed), miles (distance), feet (elevation)
        //              metric: kilometers per hour (speed), kilometers (distance), meters (elevation)
        //              <blank>: meters per second (speed), meters (distance), meters (elevation)
        //      $fetch_mode (optional) = method to fetch data from Strava servers. Valid inpute: 0 or 1
        //              0: Fetch data via curl method (recommended for security reasons)
        //              1: fetch data using php functions fopen() & file_get_contents() (offered as an alternative on systems without curl access)
        //
        //    Returns a String containing the strava login token for use in api calls that require authenticated users.
        //
    	function __construct($userid = "", $token = "", $units = "imperial", $fetch_mode = 0) {
            $this->strava_userid = $userid;
            $this->strava_units = $units;
            $this->strava_token = $token;
            $this->strava_fetch_mode = $fetch_mode;
    
            if(trim($fetch_mode) == ""){
                $this->strava_fetch_mode = 0;
            }
    	}
    
    
    
    
        //FUNCTION: login
        //   Login to Strava with email/password provided during construction via restful api interface
        //
        //   Accepts
        //      $email (optional) = email address of strava account -- default is class initialzed
        //      $password (optional) = password for strava account -- default is class initialized
        //      $mute_errors (optional) = true/fales -- When true, exception errors will be silenced. Function till simply return false.
        //
        //    Returns a String containing the strava login token for use in api calls that require authenticated users.
        //
        public function login($email = "", $password = "", $mute_errors = false){
    
        	if(!$email || trim($email)=="" || !$password || trim($password)==""){
                if(!$mute_errors){
        		    throw new Exception("Strava Email & Password required to obtain authorization token.");
                }
        	}
    
            //api documentation: https://stravasite-main.pbworks.com/w/page/51754304/v2%20authentication%20login
        	$login_token=$this->do_post_request("https://www.strava.com/api/v2/authentication/login", array("email" => $email, "password" => $password) );
        	$login_token=json_decode($login_token, true);
        
        	if(isset($login_token['error'])){
                if(!$mute_errors){
        		  throw new Exception("Login Error: The Strava Email or Password provided is incorrect.");
                }
        		return false;
        	}else{
        		return $login_token['token'];
        	}
        }
        
       
     
     
         //FUNCTION: get_athlete_details
        //    Gets users details.
        //
        //    Accepts
        //      $id (optional) = id/username of Strava user. -- default is class initialized
        //      $mute_errors (optional) = true/fales -- When true, exception errors will be silenced. Function till simply return false.
        //
        //    Returns Array
        //      ['id'] => ride id
        //      ['name'] => ride name
        //
        public function get_athlete_details($id = "", $strava_auth_token = false, $mute_errors = false){
    
            if( !$strava_auth_token ){
            	$strava_auth_token=$this->strava_token;
    
                if(!$mute_errors && (!$strava_auth_token || trim($strava_auth_token)=="")){
        		    throw new Exception("Strava authorization token required to retrieve athlete details.");
                }
            }
            
        	if(!$id || trim($id)==""){
                $id = $this->strava_userid;
                
                if(!$id || trim($id)==""){
                    if(!$mute_errors){
        		      throw new Exception("Strava User ID required to athlete details.");
                    }
                    return false;
                }
        	}
            
            //api documentation: https://stravasite-main.pbworks.com/w/page/51754302/v2%20athletes%20show
            if($this->strava_fetch_mode == 0){
            	$json_athlete=$this->get_url("http://www.strava.com/api/v2/athletes/".$id."?token=".$strava_auth_token);
            }else if($this->strava_fetch_mode == 1){
            	$json_athlete=file_get_contents("http://www.strava.com/api/v2/athletes/".$id."?token=".$strava_auth_token);
            }
    
        	$json_athlete=json_decode($json_athlete, true);
     
        	if(isset($json_athlete['error'])){
                if(!$mute_errors){
            		throw new Exception("Athlete Retrieval Error: {$json_athlete['error']}");
                }
        		return false;
        	}else{  
            	return $json_athlete;
            }
        }
        
        
        
           
        //FUNCTION: get_rides
        //    Gets a list of rides for a specific user. 
        //
        //    Accepts
        //      $id (optional) = id/username of Strava user. -- default is class initialized
        //      $mute_errors (optional) = true/fales -- When true, exception errors will be silenced. Function till simply return false.
        //
        //    Returns array of arrays
        //      [x]['id'] => ride id
        //      [x]['name'] => ride name
        //
        public function get_rides($id = "", $mute_errors = false){
    
        	if(!$id || trim($id)==""){
                $id = $this->strava_userid;
                
                if(!$id || trim($id)==""){
                    if(!$mute_errors){
        		      throw new Exception("Strava User ID required to retrieve rides.");
                    }
                    return false;
                }
        	}
            
            //api documentation: https://stravasite-main.pbworks.com/w/page/51754146/Strava%20REST%20API%20Method%3A%20rides%20index
            if($this->strava_fetch_mode == 0){
                $json_rides=$this->get_url("http://app.strava.com/api/v1/rides?athleteId=".$id);
            }else if($this->strava_fetch_mode == 1){
                $json_rides=file_get_contents("http://app.strava.com/api/v1/rides?athleteId=".$id);
            }
    
        	$json_rides=json_decode($json_rides, true);
     
        	if(isset($json_rides['error'])){
                if(!$mute_errors){
            		throw new Exception("Rides Retrieval Error: {$json_rides['error']}");
                }
        		return false;
        	}else{  
            	return $json_rides['rides'];
            }
        }
        
    
    
    
        //FUNCTION: get_ride_details
        //   Get details about a specific ride.
        //
        //    Accepts
        //      $id (required) = id of Strava ride for retrieval
        //      $mute_errors (optional) = true/fales -- When true, exception errors will be silenced. Function till simply return false.
        //
        //    Returns Array
        //      ['version'] => version number of the ride. Useful if syncing to a local db.
        //      ['id'] => ride id
        //      ['name'] => ride name
        //      ['start_date_local'] => time of ride start as unix timestamp
        //      ['elapsed_time'] => elapsed time in format hh:mm:ss
        //      ['moving_time'] => moving time in format hh:mm:ss
        //      ['distance'] => distance traveled in miles/kilometer/meters depending on set units during construct (Default: Imperial -- Miles)
        //      ['average_speed'] => average speed in miles per hour/kilometer per hour/meters per second depending on set units during construct (Default: Imperial -- Miles)
        //      ['maximum_speed'] => maximum speed in miles per hour/kilometer per hour/meters per second depending on set units during construct (Default: Imperial -- Miles)
        //      ['average_power'] => average power expended in watts
        //      ['calories'] => estimated calories burned
        //      ['athlete'] => array of rides athelete details.
        //              ['id']=rider id
        //              ['name']=rider name
        //              ['username']=rider username
        //      ['bike'] => array of rides bike details.
        //              ['id']=bike id
        //              ['name']=bike name
        //      ['elevation_gain'] => elevation gain in feet/meters depending on set units during construct (Default: Imperial -- Feet)
        //      ['location'] => city the ride took place in
        //      ['startlatlng'] => array of coordinates for start point.
        //              [0]=latitude
        //              [1]=longitude
        //      ['end_latlng'] => array of coordinates for end point.
        //              [0]=latitude
        //              [1]=longitude
        //
        public function get_ride_details($id, $mute_errors = false){
        
                if(!$id || trim($id)==""){
                    if(!$mute_errors){
                        throw new Exception("$id required to retrieve ride details.");
                    }
                    return false;
                }
    
            //not all detail is available by each version of the api. For this reason we poll both and merge the information we're interested in.    
            //api documentation: https://stravasite-main.pbworks.com/w/page/51754310/v2%20rides%20show
            if($this->strava_fetch_mode == 0){
                $json_ride=$this->get_url("http://www.strava.com/api/v2/rides/".$id);
            }else if($this->strava_fetch_mode == 1){
                $json_ride=file_get_contents("http://www.strava.com/api/v2/rides/".$id);
            }
    
        	$json_ride=json_decode($json_ride, true);
            //api documentation: https://stravasite-main.pbworks.com/w/page/51754148/Strava%20REST%20API%20Method%3A%20rides%20show
            if($this->strava_fetch_mode == 0){
                $json_ride2=$this->get_url("http://www.strava.com/api/v1/rides/".$id);
            }else if($this->strava_fetch_mode == 1){
                $json_ride2=file_get_contents("http://www.strava.com/api/v1/rides/".$id);
            }
    
        	$json_ride2=json_decode($json_ride2, true);
            
            $json_ride['ride']['version'] = $json_ride['version'];
            $json_ride['ride']['athlete'] = $json_ride2['ride']['athlete'];
            $json_ride['ride']['bike'] = $json_ride2['ride']['bike'];
            $json_ride['ride']['maximum_speed'] = $json_ride2['ride']['maximumSpeed']/3600; //converts from meters/hour to meters/second
            $json_ride['ride']['calories'] = $this->watts_to_calories($json_ride2['ride']['averageWatts'], $json_ride['ride']['moving_time']);
            $json_ride['ride']['average_power'] = round($json_ride2['ride']['averageWatts'], 0); //round avg power. the decimals are worthless in this case.
    
            unset($json_ride2); //we're through with the redundant ride query. Unset the associated var.
            
        	if(isset($json_ride['error'])){
                if(!$mute_errors){
            		throw new Exception("Ride Details Retrieval Error: {$json_ride['error']}");
                }
        		return false;
        	}else{
                $json_ride['ride']['elapsed_time'] = $this->seconds_to_hms($json_ride['ride']['elapsed_time']);
                $json_ride['ride']['moving_time'] = $this->seconds_to_hms($json_ride['ride']['moving_time']);
                $json_ride['ride']['start_date_local'] = $this->strava_time_to_unix($json_ride['ride']['start_date_local']);
                
                //convert data as per units declaration
                if($this->strava_units == "imperial"){
                    $json_ride['ride']['distance'] = $this->meters_to_miles($json_ride['ride']['distance']);
                    $json_ride['ride']['average_speed'] = $this->meterspersecond_to_milesperhour($json_ride['ride']['average_speed']);
                    $json_ride['ride']['maximum_speed'] = $this->meterspersecond_to_milesperhour($json_ride['ride']['maximum_speed']);
                    $json_ride['ride']['elevation_gain'] = $this->meters_to_feet($json_ride['ride']['elevation_gain']);
                }else if($this->strava_units == "metric"){
                    $json_ride['ride']['distance'] = $this->meters_to_kilometers($json_ride['ride']['distance']);
                    $json_ride['ride']['average_speed'] = $this->meterspersecond_to_kilometersperhour($json_ride['ride']['average_speed']);
                    $json_ride['ride']['maximum_speed'] = $this->meterspersecond_to_kilometersperhour($json_ride['ride']['maximum_speed']);
                    $json_ride['ride']['elevation_gain'] = round($json_ride['ride']['elevation_gain'], 1);
                }
                
            	return $json_ride['ride'];
            }
        }
        
        
    
    
        //FUNCTION: get_ride_map_coordinates
        //   Get a rides map details/coordinates.
        //
        //   Accepts
        //      $ride_id (required) = Ride ID
        //      $list_type (optional) = How should the coordinates be returned.
        //              'array' = return array of arrays. (default)
        //              'string' = return a pipe delimeted string of coordinates pertaining to the.
        //      $threshold (optional) = If provided, the array of lat/lng points will be reduced to exclude "uninteresting" points within a tolerance of threshold meters.
        //      $strava_auth_token (optional/required) = strava login token. If not passed during contruct required
        //      $mute_errors (optional) = true/fales -- When true, exception errors will be silenced. Function till simply return false.
        //
        //    Returns Array of Arrays
        //      [x][0]=latitude
        //      [x][1]=longitude
        //
        public function get_ride_map_coordinates($ride_id, $list_type = "array", $threshold = 0, $strava_auth_token = false, $mute_errors = false){
    
            if( !$strava_auth_token ){
            	$strava_auth_token=$this->strava_token;
    
                if(!$mute_errors && (!$strava_auth_token || trim($strava_auth_token)=="")){
        		    throw new Exception("Strava authorization token required to retrieve ride map.");
                }
            }
            
            //api documentation: https://stravasite-main.pbworks.com/w/page/51754308/v2%20rides%20map_details
            if($this->strava_fetch_mode == 0){
                $json_ride_map_details=$this->get_url("http://www.strava.com/api/v2/rides/".$ride_id."/map_details?token=".$strava_auth_token."&threshold=".$threshold);
            }else if($this->strava_fetch_mode == 1){
                $json_ride_map_details=file_get_contents("http://www.strava.com/api/v2/rides/".$ride_id."/map_details?token=".$strava_auth_token."&threshold=".$threshold);
            }
            $json_ride_map_details=json_decode($json_ride_map_details, true);
    
    
        	if(isset($json_ride_map_details['error']) && $list_type != "json"){
                if(!$mute_errors){
            		throw new Exception("Map Coordinates Retrieval Error: {$json_ride_map_details['error']}");
                }
        		return false;
        	}else{
                if($list_type == "string"){
                    //foreach loop to flatten arrays to string. foreach selected for speed vs other loops.
                    foreach ($json_ride_map_details['latlng'] as $tmp){
                        $stringcoords.=round($tmp[0], 4).",".round($tmp[1],4)."|";
                    }
                    $stringcoords = substr($stringcoords,0,-1);
    
                    return $stringcoords;
                }else{
                    return $json_ride_map_details['latlng'];
                }
            }
        }
        
        
    
    
        //FUNCTION: get_bikes
        //    Gets a list of bikes for a specific user.
        //
        //    Accepts
        //      $id (optional) = id/username of Strava user. -- default is class initialized
        //      $mute_errors (optional) = true/fales -- When true, exception errors will be silenced. Function till simply return false.
        //
        //    Returns array of arrays
        //      [x]['id'] => bike id
        //      [x]['name'] => bike name
        //      [x]['weight'] => bike weight kilograms/lbs per second depending on set units during construct (Default: Imperial -- Lbs)
        //      [x]['frame_type'] => frame type
        //      [x]['notes'] => note attached to bike
        //      [x]['default_bike'] => is this bike the default
        //      [x]['athlete_id'] => id of bike owner
        //      [x]['retired'] => true/false -- bike retired or active
        //
        public function get_bikes($id = "", $strava_auth_token = false, $mute_errors = false){
    
            if( !$strava_auth_token ){
            	$strava_auth_token=$this->strava_token;
    
                if(!$mute_errors && (!$strava_auth_token || trim($strava_auth_token)=="")){
        		    throw new Exception("Strava authorization token required to retrieve bikes.");
                }
            }
    
        	if(!$id || trim($id)==""){
                $id = $this->strava_userid;
    
                if(!$id || trim($id)==""){
                    if(!$mute_errors){
        		      throw new Exception("Strava User ID required to retrieve bikes.");
                    }
                    return false;
                }
        	}
    
            //api documentation: https://stravasite-main.pbworks.com/w/page/51754138/Strava%20REST%20API%20Method%3A%20athletes%20bikes%20index
            if($this->strava_fetch_mode == 0){
            	$json_bikes=$this->get_url("http://www.strava.com/api/v2/athletes/".$id."/bikes?token=".$strava_auth_token);
            }else if($this->strava_fetch_mode == 1){
            	$json_bikes=file_get_contents("http://www.strava.com/api/v2/athletes/".$id."/bikes?token=".$strava_auth_token);
            }
        	$json_bikes=json_decode($json_bikes, true);
    
        	if(isset($json_bikes['error'])){
                if(!$mute_errors){
            		throw new Exception("Bikes Retrieval Error: {$json_bikes['error']}");
                }
        		return false;
        	}else{
    
                //clean the api returned data to make it easier for the end user to deal with -- remove unncessary nested array.
                $ary_return=array();
                foreach($json_bikes as $tmp){
    
                    //convert bike weight as per units declaration
                    if($this->strava_units == "imperial"){
                        $tmp['bike']['weight'] = $this->kilograms_to_lbs($tmp['bike']['weight']);
                    }
    
                    $ary_return[]=$tmp['bike'];
                }
    
            	return $ary_return;
            }
        }
    
    
    
    
        //FUNCTION: get_bike_details
        //    Gets details for a specific users bike
        //
        //    Accepts
        //      $id (optional) = id/username of Strava user. -- default is class initialized
        //      $mute_errors (optional) = true/fales -- When true, exception errors will be silenced. Function till simply return false.
        //
        //    Returns array of arrays
        //      ['id'] => bike id
        //      ['name'] => bike name
        //      ['weight'] => bike weight kilograms/lbs per second depending on set units during construct (Default: Imperial -- Lbs)
        //      ['frame_type'] => frame type
        //      ['notes'] => note attached to bike
        //      ['default_bike'] => is this bike the default
        //      ['athlete_id'] => id of bike owner
        //      ['retired'] => true/false -- bike retired or active
        //
        public function get_bike_details($athlete_id = "", $bike_id = "", $strava_auth_token = false, $mute_errors = false){
    
            if( !$strava_auth_token ){
            	$strava_auth_token=$this->strava_token;
    
                if(!$mute_errors && (!$strava_auth_token || trim($strava_auth_token)=="")){
        		    throw new Exception("Strava authorization token required to retrieve bike details.");
                }
            }
    
        	if(!$athlete_id || trim($athlete_id)==""){
                $athlete_id = $this->strava_userid;
    
                if(!$athlete_id || trim($athlete_id)==""){
                    if(!$mute_errors){
        		      throw new Exception("Strava User ID required to retrieve bike detail.");
                    }
                    return false;
                }
        	}
    
        	if(!$bike_id || trim($bike_id)==""){
                    if(!$mute_errors){
        		      throw new Exception("Strava Bike ID required to retrieve bike details.");
                    }
                    return false;
        	}
    
            //api documentation: https://stravasite-main.pbworks.com/w/page/51754139/Strava%20REST%20API%20Method%3A%20athletes%20bikes%20show
            if($this->strava_fetch_mode == 0){
            	$json_bike=$this->get_url("http://www.strava.com/api/v2/athletes/".$athlete_id."/bikes/".$bike_id."?token=".$strava_auth_token);
            }else if($this->strava_fetch_mode == 1){
            	$json_bike=file_get_contents("http://www.strava.com/api/v2/athletes/".$athlete_id."/bikes/".$bike_id."?token=".$strava_auth_token);
            }
        	$json_bike=json_decode($json_bike, true);
    
        	if(isset($json_bikes['error'])){
                if(!$mute_errors){
            		throw new Exception("Bikes Retrieval Error: {$json_bikes['error']}");
                }
        		return false;
        	}else{
                switch($json_bike['bike']['frame_type']){
                    case '1':
                        $json_bike['bike']['frame_type'] = "Mountain Bike";
                        break;
                    case '2':
                        $json_bike['bike']['frame_type'] = "Cross Bike";
                        break;
                    case '3':
                        $json_bike['bike']['frame_type'] = "Road Bike";
                        break;
                    case '4':
                        $json_bike['bike']['frame_type'] = "TT Bike";
                        break;
                }
    
                //convert bike weight as per units declaration
                if($this->strava_units == "imperial"){
                    $json_bike['bike']['weight'] = $this->kilograms_to_lbs($json_bike['bike']['weight']);
                }
    
                return $json_bike['bike'];
            }
        }
    
    
    
    
        //FUNCTION: get_efforts
        //    Gets a list of efforts for a specific ride.
        //
        //    Accepts
        //      $id (required) = ride id. -- default is class initialized
        //      $mute_errors (optional) = true/fales -- When true, exception errors will be silenced. Function till simply return false.
        //
        //    Returns array of arrays
        //      [x]['id'] => effort id
        //      [x]['start_date_local'] => effort start date
        //      [x]['elapsed_time'] => total time passed during effort
        //      [x]['moving_time'] => total time moving during effort
        //      [x]['distance'] => distance covered during effort
        //      [x]['average_speed'] => average speed during effort
        //
        public function get_efforts($id, $mute_errors = false){
    
        	if(!$id || trim($id)==""){
                if(!$mute_errors){
        		      throw new Exception("Strava Ride ID required to retrieve efforts.");
                }
                return false;
            }
    
            //api documentation: https://stravasite-main.pbworks.com/w/page/51754145/Strava%20REST%20API%20Method%3A%20rides%20efforts
            if($this->strava_fetch_mode == 0){
            	$json_efforts=$this->get_url("http://www.strava.com/api/v2/rides/".$id."/efforts");
            }else if($this->strava_fetch_mode == 1){
            	$json_efforts=file_get_contents("http://www.strava.com/api/v2/rides/".$id."/efforts");
            }
    
        	$json_efforts=json_decode($json_efforts, true);
    
        	if(isset($json_efforts['error'])){
                if(!$mute_errors){
            		throw new Exception("Efforts Retrieval Error: {$json_efforts['error']}");
                }
        		return false;
        	}else{
    
                //clean the api returned data to make it easier for the end user to deal with -- remove unncessary nested array.
                $ary_return=array();
                foreach($json_efforts['efforts'] as $tmp){
    
                    $tmp['effort']['start_date_local'] = $this->strava_time_to_unix($tmp['effort']['start_date_local']);
                    $tmp['effort']['elapsed_time'] = $this->seconds_to_hms($tmp['effort']['elapsed_time']);
                    $tmp['effort']['moving_time'] = $this->seconds_to_hms($tmp['effort']['moving_time']);
    
                    //convert data as per units declaration
                    if($this->strava_units == "imperial"){
                        $tmp['effort']['distance'] = $this->meters_to_miles($tmp['effort']['distance']);
                        $tmp['effort']['average_speed'] = $this->meterspersecond_to_milesperhour($tmp['effort']['average_speed']);
                    }else if($this->strava_units == "metric"){
                        $tmp['effort']['distance'] = $this->meters_to_kilometers($tmp['effort']['distance']);
                        $tmp['effort']['average_speed'] = $this->meterspersecond_to_kilometersperhour($tmp['effort']['average_speed']);
                    }
                    $ary_return[]=$tmp['effort'];
                }
    
            	return $ary_return;
            }
        }
    
    
    
    
        //FUNCTION: get_effort_details
        //    Gets the details of an effort
        //
        //    Accepts
        //      $id (required) = effort id. -- default is class initialized
        //      $mute_errors (optional) = true/fales -- When true, exception errors will be silenced. Function till simply return false.
        //
        //    Returns array of arrays
        //      ['id'] => effort id
        //      ['start_date_local'] => unix timestamp of effort start date
        //      ['elapsed_time'] => total time for effort
        //      ['moving_time'] => moving time for effort
        //      ['distance'] => distance covered during the effort
        //      ['elevation_gain'] => elevation gain during the effort
        //      ['average_speed'] => average speed during the effort
        //      ['maximum_speed'] => maximum speed during the effort
        //      ['average_power'] => average power expended during effort in watts
        //      ['calories'] => calories burned on effort
        //      ['segment']
        //              ['id'] => efforts segment id
        //              ['name'] => efforts segment name
        //      ['athlete'] => array of rides athelete details.
        //              ['id'] => rider id
        //              ['name'] => rider name
        //              ['username'] => rider username
        //      ['ride']
        //              ['id'] => efforts parent ride id
        //              ['name'] => efforts parent ride name
        //
        public function get_effort_details($id, $mute_errors = false){
    
        	if(!$id || trim($id)==""){
                if(!$mute_errors){
        		      throw new Exception("Strava Effort ID required to retrieve efforts.");
                }
                return false;
            }
    
            //api documentation: https://stravasite-main.pbworks.com/w/page/51754144/Strava%20REST%20API%20Method%3A%20efforts%20show
            if($this->strava_fetch_mode == 0){
                $json_effort=$this->get_url("http://www.strava.com/api/v1/efforts/".$id);
            }else if($this->strava_fetch_mode == 1){
                $json_effort=file_get_contents("http://www.strava.com/api/v1/efforts/".$id);
            }
        	$json_effort=json_decode($json_effort, true);
    
        	if(isset($json_effort['error'])){
                if(!$mute_errors){
            		throw new Exception("Effort Retrieval Error: {$json_effort['error']}");
                }
        		return false;
        	}else{
    
                //clean the api returned data to make it easier for the end user to deal with -- remove unncessary nested array.
                $json_effort['effort']['distance'] = $json_effort['effort']['distance'];
                $json_effort['effort']['average_speed'] = $json_effort['effort']['averageSpeed'] / 3600; //converts from meters/hour to meters/second
                $json_effort['effort']['maximum_speed'] = $json_effort['effort']['maximumSpeed'] / 3600; //converts from meters/hour to meters/second
                $json_effort['effort']['average_power'] = $json_effort['effort']['averageWatts'] / 3600; //converts from watt/hour to watt/second
                $json_effort['effort']['calories'] = $this->watts_to_calories($json_effort['effort']['averageWatts'], $json_effort['effort']['movingTime']);
                $json_effort['effort']['start_date_local'] = $this->strava_time_to_unix($json_effort['effort']['startDateLocal']);
                $json_effort['effort']['elapsed_time'] = $this->seconds_to_hms($json_effort['effort']['elapsedTime']);
                $json_effort['effort']['moving_time'] = $this->seconds_to_hms($json_effort['effort']['movingTime']);
                $json_effort['effort']['elevation_gain'] = $json_effort['effort']['elevationGain'];
    
                //remove keys renamed above. keys renamed for consistency with other returns as the majority of other returns are via v2 api.
                unset($json_effort['effort']['averageSpeed']);
                unset($json_effort['effort']['maximumSpeed']);
                unset($json_effort['effort']['averageWatts']);
                unset($json_effort['effort']['startDate']);
                unset($json_effort['effort']['startDateLocal']);
                unset($json_effort['effort']['timeZoneOffset']);
                unset($json_effort['effort']['elapsedTime']);
                unset($json_effort['effort']['movingTime']);
                unset($json_effort['effort']['elevationGain']);
    
                //convert data as per units declaration
                if($this->strava_units == "imperial"){
                    $json_effort['effort']['distance'] = $this->meters_to_miles($json_effort['effort']['distance']);
                    $json_effort['effort']['average_speed'] = $this->meterspersecond_to_milesperhour($json_effort['effort']['average_speed']);
                    $json_effort['effort']['maximum_speed'] = $this->meterspersecond_to_milesperhour($json_effort['effort']['maximum_speed']);
                    $json_effort['effort']['elevation_gain'] = $this->meters_to_feet($json_effort['effort']['elevation_gain']);
                }else if($this->strava_units == "metric"){
                    $json_effort['effort']['distance'] = $this->meters_to_kilometers($json_effort['effort']['distance']);
                    $json_effort['effort']['average_speed'] = $this->meterspersecond_to_kilometersperhour($json_effort['effort']['average_speed']);
                    $json_effort['effort']['maximum_speed'] = $this->meterspersecond_to_kilometersperhour($json_effort['effort']['maximum_speed']);
                    $json_effort['effort']['elevation_gain'] = round($json_effort['effort']['elevation_gain'], 1);
                }
    
                return $json_effort['effort'];
            }
        }
    
    
    
    
        //FUNCTION: do_post_request
        // (credit: Wez Furlong - http://wezfurlong.org/blog/2006/nov/http-post-from-php-without-curl/)
        //
        //    Accepts
        //      $url (required) - http/https url for api
        //      $data (required) - array of data for posting
        //      $option_headers (optional)
        //
        //    Returns any replied data
        //
        private function do_post_request($url, $data, $optional_headers = null)
        {
        	$data=http_build_query($data);
    
            if($this->strava_fetch_mode == 0){
    
                //Post data to url via curl
                $ch = curl_init();
                $timeout = 0; // set to zero for no timeout
                curl_setopt ($ch, CURLOPT_URL, $url);
                curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
                curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
                curl_setopt($ch,CURLOPT_POST, 2);
                curl_setopt($ch,CURLOPT_POSTFIELDS, $data);
                ob_start();
                curl_exec($ch);
                curl_close($ch);
                $url_response = ob_get_contents();
                ob_end_clean();
    
            }else if($this->strava_fetch_mode == 1){
    
                //Post data to URl via fopen
            	$params = array('http' => array(
                          'method' => 'POST',
                          'content' => $data
                        ));
    
            	if ($optional_headers !== null) {
            		$params['http']['header'] = $optional_headers;
            	}
    
                $ctx = stream_context_create($params);
                $fp = @fopen($url, 'rb', false, $ctx);
                if (!$fp) {
                    throw new Exception("Problem with $url, $php_errormsg");
                }
    
                $url_response = @stream_get_contents($fp);
    
            }
    
    
        	if (!$url_response) {
        		throw new Exception("Problem with $url, $php_errormsg");
        	}
        
        	return $url_response;
        }
        
        
        
    
        //FUNCTION: meters_to_feet
        //
        //   Accepts
        //      $meters (required) = meters for conversion to feet
        //
        //   Returns converted data
        //
        private function meters_to_feet($meters){
                
                $feet = $meters * 3.2808399;
                $feet = round($feet, 0);
        
                return $feet;
        }
        
        
        
    
        //FUNCTION: meters_to_miles
        //   
        //   Accepts
        //      $meters (required) = meters for conversion to miles
        //   
        //   Returns converted data
        //
        private function meters_to_miles($meters){
        
        	$miles = $meters * 0.000621371192;
        	$miles = round($miles, 1);
        
        	return $miles;
        }
        
        
    
    
        //FUNCTION: meterspersecond_to_milesperhour
        //   
        //   Accepts
        //      $meters (required) = meters for conversion to miles
        //   
        //   Returns converted data
        //
        private function meterspersecond_to_milesperhour($meters){
        
        	$miles = $meters * 2.23693629;
        	$miles = round($miles, 1);
        
        	return $miles;
        }
        
        
    
            
        //FUNCTION: meters_to_kilometers
        //   
        //   Accepts
        //      $meters (required) = meters for conversion to kilometers
        //   
        //   Returns converted data
        //
        private function meters_to_kilometers($meters){
        
                $kilometers = $meters * 0.001;
                $kilometers = round($kilometers, 1);
        
                return $kilometers;
        }
        
        
    
    
        //FUNCTION: meterspersecond_to_kilometersperhour
        //   
        //   Accepts
        //      $meters (required) = meters for conversion to miles
        //   
        //   Returns converted data
        //
        private function meterspersecond_to_kilometersperhour($meters){
        
        	$miles = $meters * 3.6;
        	$miles = round($miles, 1);
        
        	return $miles;
        }
        
        
    
        
        //FUNCTION: kilograms_to_lbs
        //
        //   Accepts
        //      $kilograms (required) = kilograms for conversion to lbs
        //
        //   Returns converted data
        //
        private function kilograms_to_lbs($kg){
    
        	$lbs = $kg * 2.20462262;
        	$lbs = round($lbs, 1);
    
        	return $lbs;
        }
    
    
    
    
        //FUNCTION: watts_to_calories
        //
        //   Accepts
        //      $watts (required) = watts for conversion to calories
        //      $time (required) = time in seconds of energy expense
        //      $calibration (optional) = number to calibrate calorie expenditure
        //
        //   Returns converted data
        //
        private function watts_to_calories($watts, $time, $calibration = 0.2145){
    
        	$calories = round((((($watts / 1000) * $time) / 4.184) / $calibration), 0);
    
        	return $calories;
        }
    
    
    
    
        //FUNCTION: strava_time_top_unix
        //   
        //   Accepts
        //      $strava_datetime (required) = string returned by Strava api representing time & date data
        //   
        //   Returns unix time stamp acceptable for use in date() function.
        //
        private function strava_time_to_unix($strava_datetime){
        
        	$timestamp = str_replace("T", " ", $strava_datetime);
        	$timestamp = str_replace("Z", " ", $timestamp);
        
        	$timestamp = strtotime($timestamp);
        
        	return $timestamp;
        }
        
        
    
    
        //FUNCTION: strava_time_top_unix
        //   
        //   Accepts
        //      $sec (required) = number of seconds to be converted
        //      $padHours (option) = true/false -- Add leading 0 before hours?
        //   
        //   Returns time formatted as hours minutes & seconds.
        //    
        private function seconds_to_hms ($sec, $padHours = false) {
        
        	//string for hours:minute:seconds
        	$hms = "";
            
        	// there are 3600 seconds in an hour
        	$hours = intval(intval($sec) / 3600);
           
        	// add to $hms, with a leading 0 if asked for
        	if($hours>0){
        		$hms .= ($padHours)
        	? str_pad($hours, 2, "0", STR_PAD_LEFT). ':'
        		: $hours. ':';
        	}
             
        	// dividing the total seconds by 60 will gives us the number of minuutes 
        	// divide by 60 again and keep the remainder for minutes past the hours
        	$minutes = intval(($sec / 60) % 60);
            
        	// then add to $hms (with a leading 0 if needed)
        	$hms .= str_pad($minutes, 2, "0", STR_PAD_LEFT). ':';
            
        	//divide the total seconds by 60 and keep the remainder for seconds
        	$seconds = intval($sec % 60);
            
        	// add to $hms, again with a leading 0 if needed
        	$hms .= str_pad($seconds, 2, "0", STR_PAD_LEFT);
            
        	return $hms;
        }
    
    
    
    
        //FUNCTION: strava_time_top_unix
        //
        //   Accepts
        //      $url (required) = url to retrieve
        //
        //   Returns time formatted as hours minutes & seconds.
        //
        private function get_url ($url) {
    
            $ch = curl_init();
            $timeout = 0; // set to zero for no timeout
            curl_setopt ($ch, CURLOPT_URL, $url);
            curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
            curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
    
            ob_start();
            curl_exec($ch);
            curl_close($ch);
            $url_response = ob_get_contents();
            ob_end_clean();
    
            return $url_response;
        }
    
    
    
    
        //cleanup our variables
        function __destruct() {
            unset($this->strava_userid);
            unset($this->strava_units);
            unset($this->strava_token);
            unset($this->strava_fetch_mode);
        }
    }
    

    Leave a Reply