PageRenderTime 39ms CodeModel.GetById 6ms RepoModel.GetById 0ms app.codeStats 0ms

/application/libraries/facebook.php

https://github.com/SMLabs/codeigniter-facebook
PHP | 505 lines | 381 code | 117 blank | 7 comment | 37 complexity | 563192788acf6e9b0357c7e355134431 MD5 | raw file
  1. <?php
  2. class facebook {
  3. private $_api_url;
  4. private $_api_key;
  5. private $_api_secret;
  6. private $_errors = array();
  7. private $_enable_debug = FALSE;
  8. function __construct()
  9. {
  10. $this->_obj =& get_instance();
  11. $this->_obj->load->library('session');
  12. $this->_obj->load->config('facebook');
  13. $this->_obj->load->helper('url');
  14. $this->_obj->load->helper('facebook');
  15. $this->_api_url = $this->_obj->config->item('facebook_api_url');
  16. $this->_api_key = $this->_obj->config->item('facebook_app_id');
  17. $this->_api_secret = $this->_obj->config->item('facebook_api_secret');
  18. $this->session = new facebookSession();
  19. $this->connection = new facebookConnection();
  20. }
  21. public function logged_in()
  22. {
  23. return $this->session->logged_in();
  24. }
  25. public function login($scope = NULL)
  26. {
  27. return $this->session->login($scope);
  28. }
  29. public function login_url($scope = NULL)
  30. {
  31. return $this->session->login_url($scope);
  32. }
  33. public function logout()
  34. {
  35. return $this->session->logout();
  36. }
  37. public function user()
  38. {
  39. return $this->session->get();
  40. }
  41. public function call($method, $uri, $data = array())
  42. {
  43. $response = FALSE;
  44. try
  45. {
  46. switch ( $method )
  47. {
  48. case 'get':
  49. $response = $this->connection->get($this->append_token($this->_api_url.$uri));
  50. break;
  51. case 'post':
  52. $response = $this->connection->post($this->append_token($this->_api_url.$uri), $data);
  53. break;
  54. }
  55. }
  56. catch (facebookException $e)
  57. {
  58. $this->_errors[] = $e;
  59. if ( $this->_enable_debug )
  60. {
  61. echo $e;
  62. }
  63. }
  64. return $response;
  65. }
  66. public function errors()
  67. {
  68. return $this->_errors;
  69. }
  70. public function last_error()
  71. {
  72. if ( count($this->_errors) == 0 ) return NULL;
  73. return $this->_errors[count($this->_errors) - 1];
  74. }
  75. public function append_token($url)
  76. {
  77. return $this->session->append_token($url);
  78. }
  79. public function set_callback($url)
  80. {
  81. return $this->session->set_callback($url);
  82. }
  83. public function enable_debug($debug = TRUE)
  84. {
  85. $this->_enable_debug = (bool) $debug;
  86. }
  87. }
  88. class facebookConnection {
  89. // Allow multi-threading.
  90. private $_mch = NULL;
  91. private $_properties = array();
  92. function __construct()
  93. {
  94. $this->_mch = curl_multi_init();
  95. $this->_properties = array(
  96. 'code' => CURLINFO_HTTP_CODE,
  97. 'time' => CURLINFO_TOTAL_TIME,
  98. 'length' => CURLINFO_CONTENT_LENGTH_DOWNLOAD,
  99. 'type' => CURLINFO_CONTENT_TYPE
  100. );
  101. }
  102. private function _initConnection($url)
  103. {
  104. $this->_ch = curl_init($url);
  105. curl_setopt($this->_ch, CURLOPT_RETURNTRANSFER, TRUE);
  106. }
  107. public function get($url, $params = array())
  108. {
  109. if ( count($params) > 0 )
  110. {
  111. $url .= '?';
  112. foreach( $params as $k => $v )
  113. {
  114. $url .= "{$k}={$v}&";
  115. }
  116. $url = substr($url, 0, -1);
  117. }
  118. $this->_initConnection($url);
  119. $response = $this->_addCurl($url, $params);
  120. return $response;
  121. }
  122. public function post($url, $params = array())
  123. {
  124. // Todo
  125. $post = '';
  126. foreach ( $params as $k => $v )
  127. {
  128. $post .= "{$k}={$v}&";
  129. }
  130. $post = substr($post, 0, -1);
  131. $this->_initConnection($url, $params);
  132. curl_setopt($this->_ch, CURLOPT_POST, 1);
  133. curl_setopt($this->_ch, CURLOPT_POSTFIELDS, $post);
  134. $response = $this->_addCurl($url, $params);
  135. return $response;
  136. }
  137. private function _addCurl($url, $params = array())
  138. {
  139. $ch = $this->_ch;
  140. $key = (string) $ch;
  141. $this->_requests[$key] = $ch;
  142. $response = curl_multi_add_handle($this->_mch, $ch);
  143. if ( $response === CURLM_OK || $response === CURLM_CALL_MULTI_PERFORM )
  144. {
  145. do {
  146. $mch = curl_multi_exec($this->_mch, $active);
  147. } while ( $mch === CURLM_CALL_MULTI_PERFORM );
  148. return $this->_getResponse($key);
  149. }
  150. else
  151. {
  152. return $response;
  153. }
  154. }
  155. private function _getResponse($key = NULL)
  156. {
  157. if ( $key == NULL ) return FALSE;
  158. if ( isset($this->_responses[$key]) )
  159. {
  160. return $this->_responses[$key];
  161. }
  162. $running = NULL;
  163. do
  164. {
  165. $response = curl_multi_exec($this->_mch, $running_curl);
  166. if ( $running !== NULL && $running_curl != $running )
  167. {
  168. $this->_setResponse($key);
  169. if ( isset($this->_responses[$key]) )
  170. {
  171. $response = new facebookResponse( (object) $this->_responses[$key] );
  172. if ( $response->__resp->code !== 200 )
  173. {
  174. $error = $response->__resp->code.' | Request Failed';
  175. if ( isset($response->__resp->data->error->type) )
  176. {
  177. $error .= ' - '.$response->__resp->data->error->type.' - '.$response->__resp->data->error->message;
  178. }
  179. throw new facebookException($error);
  180. }
  181. return $response;
  182. }
  183. }
  184. $running = $running_curl;
  185. } while ( $running_curl > 0);
  186. }
  187. private function _setResponse($key)
  188. {
  189. while( $done = curl_multi_info_read($this->_mch) )
  190. {
  191. $key = (string) $done['handle'];
  192. $this->_responses[$key]['data'] = curl_multi_getcontent($done['handle']);
  193. foreach ( $this->_properties as $curl_key => $value )
  194. {
  195. $this->_responses[$key][$curl_key] = curl_getinfo($done['handle'], $value);
  196. curl_multi_remove_handle($this->_mch, $done['handle']);
  197. }
  198. }
  199. }
  200. }
  201. class facebookResponse {
  202. private $__construct;
  203. public function __construct($resp)
  204. {
  205. $this->__resp = $resp;
  206. $data = json_decode($this->__resp->data);
  207. if ( $data !== NULL )
  208. {
  209. $this->__resp->data = $data;
  210. }
  211. }
  212. public function __get($name)
  213. {
  214. if ($this->__resp->code < 200 || $this->__resp->code > 299) return FALSE;
  215. $result = array();
  216. if ( is_string($this->__resp->data ) )
  217. {
  218. parse_str($this->__resp->data, $result);
  219. $this->__resp->data = (object) $result;
  220. }
  221. if ( $name === '_result')
  222. {
  223. return $this->__resp->data;
  224. }
  225. return $this->__resp->data->$name;
  226. }
  227. }
  228. class facebookException extends Exception {
  229. function __construct($string)
  230. {
  231. parent::__construct($string);
  232. }
  233. public function __toString() {
  234. return "exception '".__CLASS__ ."' with message '".$this->getMessage()."' in ".$this->getFile().":".$this->getLine()."\nStack trace:\n".$this->getTraceAsString();
  235. }
  236. }
  237. class facebookSession {
  238. private $_api_key;
  239. private $_api_secret;
  240. private $_token_url = 'oauth/access_token';
  241. private $_user_url = 'me';
  242. private $_data = array();
  243. function __construct()
  244. {
  245. $this->_obj =& get_instance();
  246. $this->_api_key = $this->_obj->config->item('facebook_app_id');
  247. $this->_api_secret = $this->_obj->config->item('facebook_api_secret');
  248. $this->_token_url = $this->_obj->config->item('facebook_api_url').$this->_token_url;
  249. $this->_user_url = $this->_obj->config->item('facebook_api_url').$this->_user_url;
  250. $this->_set('scope', $this->_obj->config->item('facebook_default_scope'));
  251. $this->connection = new facebookConnection();
  252. if ( !$this->logged_in() )
  253. {
  254. // Initializes the callback to this page URL.
  255. $this->set_callback();
  256. }
  257. }
  258. public function logged_in()
  259. {
  260. return ( $this->get() === NULL ) ? FALSE : TRUE;
  261. }
  262. public function logout()
  263. {
  264. $this->_unset('token');
  265. $this->_unset('user');
  266. }
  267. public function login_url($scope = NULL)
  268. {
  269. $url = "http://www.facebook.com/dialog/oauth?client_id=".$this->_api_key.'&redirect_uri='.urlencode($this->_get('callback'));
  270. if ( empty($scope) )
  271. {
  272. $scope = $this->_get('scope');
  273. }
  274. else
  275. {
  276. $this->_set('scope', $scope);
  277. }
  278. if ( !empty($scope) )
  279. {
  280. $url .= '&scope='.$scope;
  281. }
  282. return $url;
  283. }
  284. public function login($scope = NULL)
  285. {
  286. $this->logout();
  287. if ( !$this->_get('callback') ) $this->_set('callback', current_url());
  288. $url = $this->login_url($scope);
  289. return redirect($url);
  290. }
  291. public function get()
  292. {
  293. $token = $this->_find_token();
  294. if ( empty($token) ) return NULL;
  295. // $user = $this->_get('user');
  296. // if ( !empty($user) ) return $user;
  297. try
  298. {
  299. $user = $this->connection->get($this->_user_url.'?'.$this->_token_string());
  300. }
  301. catch ( facebookException $e )
  302. {
  303. $this->logout();
  304. return NULL;
  305. }
  306. // $this->_set('user', $user);
  307. return $user;
  308. }
  309. private function _find_token()
  310. {
  311. $token = $this->_get('token');
  312. if ( !empty($token) )
  313. {
  314. if ( !empty($token->expires) && intval($token->expires) >= time() )
  315. {
  316. // Problem, token is expired!
  317. return $this->logout();
  318. }
  319. $this->_set('token', $token);
  320. return $this->_token_string();
  321. }
  322. if ( !isset($_GET['code']) )
  323. {
  324. return $this->logout();
  325. }
  326. if ( !$this->_get('callback') ) $this->_set('callback', current_url());
  327. $token_url = $this->_token_url.'?client_id='.$this->_api_key."&client_secret=".$this->_api_secret."&code=".$_GET['code'].'&redirect_uri='.urlencode($this->_get('callback'));
  328. try
  329. {
  330. $token = $this->connection->get($token_url);
  331. }
  332. catch ( facebookException $e )
  333. {
  334. $this->logout();
  335. redirect($this->_strip_query());
  336. return NULL;
  337. }
  338. $this->_unset('callback');
  339. if ( $token->access_token )
  340. {
  341. if ( !empty($token->expires) )
  342. {
  343. $token->expires = strval(time() + intval($token->expires));
  344. }
  345. $this->_set('token', $token);
  346. redirect($this->_strip_query());
  347. }
  348. return $this->_token_string();
  349. }
  350. private function _get($key)
  351. {
  352. $key = '_facebook_'.$key;
  353. return $this->_obj->session->userdata($key);
  354. }
  355. private function _set($key, $data)
  356. {
  357. $key = '_facebook_'.$key;
  358. $this->_obj->session->set_userdata($key, $data);
  359. }
  360. private function _unset($key)
  361. {
  362. $key = '_facebook_'.$key;
  363. $this->_obj->session->unset_userdata($key);
  364. }
  365. public function set_callback($url = NULL)
  366. {
  367. $this->_set('callback', $this->_strip_query($url));
  368. }
  369. private function _token_string()
  370. {
  371. return 'access_token='.$this->_get('token')->access_token;
  372. }
  373. public function append_token($url)
  374. {
  375. if ( $this->_get('token') ) $url .= '?'.$this->_token_string();
  376. return $url;
  377. }
  378. private function _strip_query($url = NULL)
  379. {
  380. if ( $url === NULL )
  381. {
  382. $url = ( empty($_SERVER['HTTPS']) ) ? 'http' : 'https';
  383. $url .= '://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
  384. }
  385. $parts = explode('?', $url);
  386. return $parts[0];
  387. }
  388. }