<?php 

// Facebook Graph Get - send a request to Facebook's Graph API and return JSON_decoded response.
// Returns false on errors and sets $error.  This is a simple interface to the most common Facebook
// Graph requests that this plugin requires.  For more complicated or advanced Facebook requests it
// may be easier to use the SDK:
// Facebook PHP SDK:          https://developers.facebook.com/docs/reference/php
// Facebook PHP SDK (github): https://github.com/facebook/php-graph-sdk
// Usage: fb_graph("/ededed", ['key' => 'value'], $errors);
/*
  $response = fb_graph('/debug_token', [
                'input_token'  => $shortLivedToken,
                'access_token' => $appAccessToken
              ], $errors) or die("Facebook Login Errors: $errors"); 
*/
function fb_graph($urlPath, $queryParams = [], &$errors = null) {
  if (!$urlPath) { $errors = "No urlPath specified!"; return false; }
  $errors    = '';
  
  // get graph URL
  $graphUrl  = "https://graph.facebook.com/" .fbl_settings('api_version'). $urlPath;
  
  // make request
  $curlOptions = [];
  $curlOptions[CURLOPT_CONNECTTIMEOUT] = 4; // default 2, seconds to wait while connecting
  $curlOptions[CURLOPT_TIMEOUT]        = 6; // default 4, total max seconds for cURL execution
  $responseJSON = curl_get($graphUrl, $queryParams, $requestInfo, $curlOptions);
  $response     = json_decode($responseJSON, true);
  if (json_last_error()) { $errors .= "Error decoding JSON response: " .json_last_error_msg(). "\n"; }
  
  // get response
  if     (!empty($response['error']))         { $errors .= "{$response['error']['message']} (Type: {$response['error']['type']}, Code: {$response['error']['code']})\n"; }
  elseif ($requestInfo['http_code'] != '200') { $errors .= "Unexpected server response (HTTP Code: {$requestInfo['http_code']})\n"; }
  elseif ($responseJSON == '')                { $errors .= "Empty response from server\n"; }

  /*
  print "DEBUG: ";
  showme([
    'graphUrl'    => $graphUrl,
    'queryParams' => $queryParams,
    'httpcode'    => $requestInfo['http_code'],
    'response'    => $response,
    'errors'      => $errors
  ]);
  */
  
  // 
  if ($errors) { return false; }
  return $response;
}


// Return debug info about a token, or false and sets $errors on failure
// Usage: $debugToken = fbg_debugToken( $token, $errors ) or die("debug token errors: $errors"); 
// Debug: Validate token manually: graph.facebook.com/debug_token?input_token=your_token_here
function fbg_debugToken($token, &$errors = '') {
  if (!$token) { $errors = "No token specified!"; return false; }
  $errors = '';
  
  // request token info
  $response = fb_graph('/debug_token', [
                'input_token'  => $token,
                'access_token' => _fbg_appAccessToken(),
              ], $errors);
  if ($errors) { return false; } 
  
  //
  return $response;
}


// Check if facebook login token is valid.  On valid token returns true, on invalid returns false and sets $errors
// Usage: fbg_isValidToken( $_REQUEST['accessToken'], $errors ) or die("Invalid token: $errors"); 
// Debug: Validate token manually: graph.facebook.com/debug_token?input_token=your_token_here
function fbg_isValidToken($token, &$errors = '') {
  if (!$token) { $errors = "No token specified!"; return false; }
  $errors = '';
  
  // get token info
  $response = fbg_debugToken( $token, $errors );
  if ($errors) { return false; } 
  
  // check token info
  if     (!$response['data']['is_valid'])                        { $errors = "token isn't valid"; }
  elseif (isset($response['data']['error']))                     { $errors = "error with token"; }
  elseif ($response['data']['app_id'] != fbl_settings('app_id')) { $errors = "appid doesn't match"; }
  elseif (!$response['data']['user_id'])                         { $errors = "no user_id"; }
  if ($errors) { return false; }
  
  //
  return true; 
}

// Upgrade a short-lived token to a long-lived token - regular/short-term tokens last ~1-2 hours, long-term tokens last ~60 days
// Note: We do this in case we want to make requests on the users behalf to facebook over time from the server
// Returns new token on success, on failure returns false and sets $errors
// Usage: $longLivedToken = fbg_upgradeToken($token, $errors) or die("Error upgrading token: $errors"); 
function fbg_upgradeToken($token, &$errors = '') {
  if (!$token) { $errors = "No token specified!"; return false; }
  $errors = '';
  
  // request token upgrade
  $response = fb_graph('/oauth/access_token', [
                'grant_type'        => 'fb_exchange_token',
                'client_id'         => fbl_settings('app_id'),
                'client_secret'     => fbl_settings('app_secret'),
                'fb_exchange_token' => $token,
              ], $errors);
  if ($errors) { return false; } 

  // error checking
  if     (!empty($response['error']))         { $error = "error getting long-lived token"; }
  elseif (empty($response['access_token']))   { $error = "no long-lived token returned"; }
  if ($errors) { return false; }
  
  //
  $longLivedToken = $response['access_token'];
  return $longLivedToken;

}


// returns app access token - usage: _fbg_appAccessToken();
function _fbg_appAccessToken() {
  // appAccessToken: This is an alternate method to requesting token: https://developers.facebook.com/docs/facebook-login/access-tokens/#apptokens  
  $appAccessToken   = fbl_settings('app_id') .'|'. fbl_settings('app_secret');
  return $appAccessToken;
}

// Show error message for old functions from Facebook Login v1.xx
function ____oldFacebookFunctions_showError____() {
  @trigger_error("Facebook Login Plugin - Old code detected, see readme.txt for upgrade instructions.", E_USER_NOTICE);
  $escapedError = jsencode("We're currently upgrading our Facebook Login plugin, please try again later.");
  return "javascript:alert('$escapedError');";
}
function facebookLogin_getFacebookLoginUrl($popup = false) { return ____oldFacebookFunctions_showError____(); }
function facebookLogin_getFacebookLoginUrl_popupOnClick() { return ____oldFacebookFunctions_showError____(); }

// eof