PageRenderTime 50ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/includes/facebook-php-sdk/class-facebook-wp.php

https://gitlab.com/0072016/wordpress
PHP | 426 lines | 219 code | 58 blank | 149 comment | 69 complexity | b78aa8ac93857051d8d2b015e0d18898 MD5 | raw file
  1. <?php
  2. // parent class
  3. if ( ! class_exists( 'WP_Facebook' ) )
  4. require_once( dirname( __FILE__ ) . '/facebook.php' );
  5. /**
  6. * Override default Facebook SDK for PHP behaviors with WordPress-friendly features
  7. *
  8. * A class combining the user-session-focused Facebook SDK for PHP and server-to-server communication methods of app access token data access into a single WordPress HTTP API friendly wrapper class
  9. *
  10. * @since 1.0
  11. */
  12. class Facebook_WP_Extend extends WP_Facebook {
  13. /**
  14. * Uniquely identify requests sent from the WordPress site by WordPress version and site url
  15. *
  16. * @since 1.4
  17. * @global string $wp_version communicate the version of WordPress making the request
  18. * @uses home_url() include the URL of WordPress site in the User-Agent string
  19. * @return string User-Agent string for use in requests to Facebook
  20. */
  21. public static function generate_user_agent() {
  22. global $wp_version;
  23. return apply_filters( 'http_headers_useragent', 'WordPress/' . $wp_version . '; ' . home_url() . '; facebook-php-' . self::VERSION . '-wp' );
  24. }
  25. /**
  26. * Handle a response from the WordPress HTTP API
  27. * Checks if the response is a WP_Error object. converts WP_Error to a WP_FacebookApiException for compatibility with the Facebook PHP SDK
  28. * If the HTTP response code is not 200 OK then a WP_FacebookApiException is thrown with error information returned by Facebook
  29. *
  30. * @since 1.1.6
  31. * @throws WP_FacebookApiException
  32. * @param WP_Error|array $response WP_HTTP response
  33. * @return string HTTP response body
  34. */
  35. public static function handle_response( $response ) {
  36. if ( is_wp_error( $response ) ) {
  37. throw new WP_FacebookApiException( array( 'error_code' => $response->get_error_code(), 'error_msg' => $response->get_error_message() ) );
  38. } else if ( wp_remote_retrieve_response_code( $response ) != '200' ) {
  39. $fb_response = json_decode( wp_remote_retrieve_body( $response ) );
  40. throw new WP_FacebookApiException( array(
  41. 'error_code' => $fb_response->error->code,
  42. 'error' => array(
  43. 'message' => $fb_response->error->message,
  44. 'type' => $fb_response->error->type
  45. )
  46. ) );
  47. }
  48. return wp_remote_retrieve_body( $response );
  49. }
  50. /**
  51. * Override Facebook PHP SDK cURL function with WP_HTTP
  52. * Facebook PHP SDK is POST-only
  53. *
  54. * @since 1.0
  55. * @todo add file upload support if we care
  56. * @param string $url request URL
  57. * @param array $params parameters used in the POST body
  58. * @param CurlHandler $ch Initialized curl handle. unused: here for compatibility with parent method parameters only
  59. * @throws WP_FacebookApiException
  60. * @return string HTTP response body
  61. */
  62. protected function makeRequest( $url, $params, $ch=null ) {
  63. if ( empty( $url ) || empty( $params ) )
  64. throw new WP_FacebookApiException( array( 'error_code' => 400, 'error' => array( 'type' => 'makeRequest', 'message' => 'Invalid parameters and/or URI passed to makeRequest' ) ) );
  65. return self::handle_response( wp_remote_post( $url, array(
  66. 'redirection' => 0,
  67. 'httpversion' => '1.1',
  68. 'timeout' => 60,
  69. 'user-agent' => self::generate_user_agent(),
  70. 'headers' => array( 'Connection' => 'close' , 'Content-Type' => 'application/x-www-form-urlencoded' ),
  71. 'sslverify' => false, // warning: might be overridden by 'https_ssl_verify' filter
  72. 'body' => http_build_query( $params, '', '&' )
  73. ) ) );
  74. }
  75. /**
  76. * GET request sent through WordPress HTTP API with custom parameters
  77. *
  78. * @since 1.1.6
  79. * @param string absolute URL
  80. * @return array decoded json_decode() response as an associative array
  81. */
  82. public static function get_json_url( $url ) {
  83. if ( ! is_string( $url ) && $url )
  84. return array();
  85. $response = self::handle_response( wp_remote_get( $url, array(
  86. 'redirection' => 0,
  87. 'httpversion' => '1.1',
  88. 'timeout' => 5,
  89. 'headers' => array( 'Connection' => 'close' ),
  90. 'user-agent' => self::generate_user_agent()
  91. ) ) );
  92. if ( $response )
  93. return json_decode( $response, true );
  94. return array();
  95. }
  96. /**
  97. * Submit a request to the Facebook Graph API outside of the Facebook PHP SDK
  98. *
  99. * @param string $path Facebook Graph API endpoint
  100. * @param string $method HTTP method
  101. * @param array $params parameters to pass to the Graph API
  102. * @return array|null data response from Graph API
  103. */
  104. public static function graph_api( $path, $method = 'GET', $params = array() ) {
  105. if ( ! is_string( $path ) )
  106. return;
  107. $path = ltrim( $path, '/' ); // normalize the leading slash
  108. if ( ! $path )
  109. return;
  110. // pass a reference to WordPress plugin origin with each request
  111. if ( ! is_array( $params ) )
  112. $params = array();
  113. if ( ! isset( $params['ref'] ) )
  114. $params['ref'] = 'fbwpp';
  115. foreach ( $params as $key => $value ) {
  116. if ( ! is_string( $value ) )
  117. $params[$key] = json_encode( $value );
  118. }
  119. $url = self::$DOMAIN_MAP['graph'] . $path;
  120. $http_args = array(
  121. 'redirection' => 0,
  122. 'httpversion' => '1.1',
  123. 'sslverify' => false, // warning: might be overridden by 'https_ssl_verify' filter
  124. 'headers' => array( 'Connection' => 'close' ),
  125. 'user-agent' => self::generate_user_agent()
  126. );
  127. if ( $method === 'GET' ) {
  128. if ( ! empty( $params ) )
  129. $url .= '?' . http_build_query( $params, '', '&' );
  130. $http_args['timeout'] = 5;
  131. $response = self::handle_response( wp_remote_get( $url, $http_args ) );
  132. } else {
  133. // POST
  134. // WP_HTTP does not support DELETE verb. store as method param for interpretation by Facebook Graph API server
  135. if ( $method === 'DELETE' )
  136. $params['method'] = 'DELETE';
  137. $http_args['timeout'] = 60;
  138. $http_args['body'] = http_build_query( $params, '', '&' );
  139. $http_args['headers']['Content-Type'] = 'application/x-www-form-urlencoded';
  140. $response = self::handle_response( wp_remote_post( $url, $http_args ) );
  141. }
  142. if ( isset( $response ) && $response )
  143. return json_decode( $response, true );
  144. }
  145. /**
  146. * Invoke the Graph API for server-to-server communication using an application access token (no user session)
  147. *
  148. * @since 1.2
  149. * @param string $path The Graph API URI endpoint path component
  150. * @param string $method The HTTP method (default 'GET')
  151. * @param array $params The query/post data
  152. * @uses \Facebook_WP_Extend::graph_api()
  153. *
  154. * @return array|null The decoded response object
  155. * @throws WP_FacebookApiException
  156. */
  157. public static function graph_api_with_app_access_token( $path, $method = 'GET', $params = array() ) {
  158. global $facebook_loader;
  159. if ( ! ( isset( $facebook_loader ) && $facebook_loader->app_access_token_exists() ) )
  160. return;
  161. if ( ! is_array( $params ) )
  162. $params = array();
  163. $params['access_token'] = $facebook_loader->credentials['access_token'];
  164. if ( isset( $facebook_loader->credentials['appsecret_proof'] ) )
  165. $params['appsecret_proof'] = $facebook_loader->credentials['appsecret_proof'];
  166. return self::graph_api( $path, $method, $params );
  167. }
  168. /**
  169. * Retrieve Facebook permissions assigned to the application by a specific Facebook user id
  170. *
  171. * @since 1.2
  172. * @param string $facebook_id Facebook user identifier
  173. * @return array Facebook permissions as keys in an associative array
  174. */
  175. public static function get_permissions_by_facebook_user_id( $facebook_id ) {
  176. if ( ! ( is_string( $facebook_id ) && $facebook_id ) )
  177. return array();
  178. $response = self::graph_api_with_app_access_token( $facebook_id . '/permissions', 'GET' );
  179. if ( is_array( $response ) && isset( $response['data'][0] ) ) {
  180. $response = $response['data'][0];
  181. $permissions = array();
  182. foreach( $response as $permission => $exists ) {
  183. $permissions[$permission] = true;
  184. }
  185. return $permissions;
  186. }
  187. return array();
  188. }
  189. /**
  190. * Request an access token from the Facebook OAuth endpoint
  191. *
  192. * @since 1.5
  193. * @param array $params associative array of query parameters
  194. * @return string access token
  195. */
  196. public static function get_access_token( $params ) {
  197. if ( ! is_array( $params ) || empty( $params ) )
  198. return '';
  199. try {
  200. $response = self::handle_response( wp_remote_get( self::$DOMAIN_MAP['graph'] . 'oauth/access_token?' . http_build_query( $params, '', '&' ), array(
  201. 'redirection' => 0,
  202. 'httpversion' => '1.1',
  203. 'timeout' => 5,
  204. 'headers' => array( 'Connection' => 'close' ),
  205. 'user-agent' => self::generate_user_agent()
  206. ) ) );
  207. } catch( WP_FacebookApiException $e ) {
  208. return '';
  209. }
  210. if ( ! ( is_string( $response ) && $response ) )
  211. return '';
  212. $response_params = array();
  213. wp_parse_str( $response, $response_params );
  214. if ( isset( $response_params['access_token'] ) && $response_params['access_token'] )
  215. return $response_params['access_token'];
  216. return '';
  217. }
  218. /**
  219. * Trade an application id and a application secret for an application token used for future requests
  220. *
  221. * @since 1.4
  222. * @param string $app_id Facebook application identifier
  223. * @param string $app_secret Facebook application secret
  224. * @uses \Facebook_WP_Extend::get_access_token()
  225. * @return string access token or empty string if error
  226. */
  227. public static function get_app_access_token( $app_id, $app_secret ) {
  228. if ( ! ( is_string( $app_id ) && $app_id && is_string( $app_secret ) && $app_secret ) )
  229. return '';
  230. return self::get_access_token( array( 'client_id' => $app_id, 'client_secret' => $app_secret, 'grant_type' => 'client_credentials' ) );
  231. }
  232. /**
  233. * Exchange a short-term access token for a long-lived access token
  234. *
  235. * @since 1.5
  236. * @link https://developers.facebook.com/docs/facebook-login/access-tokens/#extending Access Tokens: Extending Access Tokens
  237. * @uses \Facebook_WP_Extend::get_access_token()
  238. * @param string $token existing access token
  239. * @return string long-lived access token
  240. */
  241. public static function exchange_token( $token ) {
  242. global $facebook_loader;
  243. if ( ! ( is_string( $token ) && $token && isset( $facebook_loader ) && isset( $facebook_loader->credentials ) && isset( $facebook_loader->credentials['app_id'] ) && isset( $facebook_loader->credentials['app_secret'] ) ) )
  244. return '';
  245. return self::get_access_token( array( 'client_id' => $facebook_loader->credentials['app_id'], 'client_secret' => $facebook_loader->credentials['app_secret'], 'grant_type' => 'fb_exchange_token', 'fb_exchange_token' => $token ) );
  246. }
  247. /**
  248. * Get application details including app name, namespace, link, and more.
  249. *
  250. * Requests application data server-to-server without the Facebook SDK for PHP or an app access token
  251. *
  252. * @since 1.4
  253. * @link https://developers.facebook.com/docs/graph-api/reference/app/ Application object and fields
  254. * @uses \Facebook_WP_Extend::get_json_url()
  255. * @param string $app_id Facebook application identifier
  256. * @param array $fields app fields to retrieve. if blank a default set will be returned
  257. * @return array application data response from Facebook API
  258. */
  259. public static function get_app_details( $app_id = '', $fields = null ) {
  260. if ( ! ( is_string( $app_id ) && $app_id ) )
  261. return array();
  262. $url = self::$DOMAIN_MAP['graph'] . $app_id;
  263. // switch to HTTP for server configurations not supporting HTTPS
  264. if ( substr_compare( $url, 'https://', 0, 8 ) === 0 && ! wp_http_supports( array( 'ssl' => true ) ) )
  265. $url = 'http://' . substr( $url, 8 );
  266. if ( ! $url )
  267. return array();
  268. if ( is_array( $fields ) && ! empty( $fields ) )
  269. $url .= '?' . http_build_query( array( 'fields' => implode( ',', $fields ) ), '', '&' );
  270. try {
  271. $app_info = self::get_json_url( $url );
  272. } catch( WP_FacebookApiException $e ) {
  273. return array();
  274. }
  275. if ( is_array( $app_info ) && isset( $app_info['id'] ) )
  276. return $app_info;
  277. return array();
  278. }
  279. /**
  280. * Get application details based on an application access token
  281. *
  282. * @since 1.4
  283. * @link https://developers.facebook.com/docs/graph-api/reference/app/ Application object and fields
  284. * @uses \Facebook_WP_Extend::graph_api()
  285. * @param string $access_token application access token
  286. * @param array $fields request specific application fields
  287. * @param string $app_secret_proof hashed access token
  288. * @return array application information returned by Facebook servers
  289. */
  290. public static function get_app_details_by_access_token( $access_token, $fields, $app_secret_proof = '' ) {
  291. if ( ! ( is_string( $access_token ) && $access_token ) )
  292. return array();
  293. $params = array( 'access_token' => $access_token );
  294. if ( is_string( $app_secret_proof ) && $app_secret_proof )
  295. $params['appsecret_proof'] = $app_secret_proof;
  296. if ( is_array( $fields ) && ! empty( $fields ) ) {
  297. if ( ! in_array( 'id', $fields, true ) )
  298. $fields[] = 'id';
  299. $params['fields'] = implode( ',', $fields );
  300. }
  301. try {
  302. $app_info = self::graph_api( 'app', 'GET', $params );
  303. } catch( WP_FacebookApiException $e ) {
  304. return array();
  305. }
  306. if ( is_array( $app_info ) && isset( $app_info['id'] ) )
  307. return $app_info;
  308. return array();
  309. }
  310. /**
  311. * Persist data stored by the Facebook SDK for JavaScript inside WordPress user meta storage
  312. *
  313. * Provides the implementations of the inherited abstract methods. The implementation uses user meta to maintain a store for authorization codes, user ids, CSRF states, and access tokens.
  314. *
  315. * @since 1.0
  316. */
  317. protected function setPersistentData( $key, $value ) {
  318. if ( ! in_array( $key, self::$kSupportedKeys ) ) {
  319. self::errorLog( 'Unsupported key passed to setPersistentData.' );
  320. return;
  321. }
  322. // load user functions
  323. if ( ! class_exists( 'Facebook_User' ) )
  324. require_once( dirname( dirname( dirname(__FILE__) ) ) . '/facebook-user.php' );
  325. Facebook_User::update_user_meta( get_current_user_id(), $key, $value );
  326. }
  327. /**
  328. * Get data persisted by the Facebook PHP SDK using WordPress-specific access methods
  329. *
  330. * @since 1.0
  331. */
  332. protected function getPersistentData( $key, $default = false ) {
  333. if ( ! in_array( $key, self::$kSupportedKeys ) ) {
  334. self::errorLog( 'Unsupported key passed to getPersistentData.' );
  335. return $default;
  336. }
  337. // load user functions
  338. if ( ! class_exists( 'Facebook_User' ) )
  339. require_once( dirname( dirname( dirname(__FILE__) ) ) . '/facebook-user.php' );
  340. return Facebook_User::get_user_meta( get_current_user_id(), $key, true );
  341. }
  342. /**
  343. * Delete data persisted by the Facebook PHP SDK using WordPress-specific access method
  344. *
  345. * @since 1.0
  346. */
  347. protected function clearPersistentData( $key ) {
  348. if ( ! in_array( $key, self::$kSupportedKeys ) ) {
  349. self::errorLog( 'Unsupported key passed to clearPersistentData.' );
  350. return;
  351. }
  352. // load user functions
  353. if ( ! class_exists( 'Facebook_User' ) )
  354. require_once( dirname( dirname( dirname(__FILE__) ) ) . '/facebook-user.php' );
  355. Facebook_User::delete_user_meta( get_current_user_id(), $key );
  356. }
  357. /**
  358. * Delete data persisted by the Facebook PHP SDK for every possible Facebook PHP SDK data key
  359. *
  360. * @since 1.0
  361. */
  362. protected function clearAllPersistentData() {
  363. foreach ( self::$kSupportedKeys as $key ) {
  364. $this->clearPersistentData($key);
  365. }
  366. }
  367. }
  368. ?>