PageRenderTime 32ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Zend/Service/Facebook.php

https://github.com/A-Shevchenko/oauth-2---facebook---zend-framework-components
PHP | 854 lines | 345 code | 124 blank | 385 comment | 60 complexity | 4901e3972594b27014f020477db561af MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Service
  17. * @subpackage Facebook
  18. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version
  21. */
  22. /**
  23. * @see Zend_Rest_Client
  24. */
  25. require_once 'Zend/Rest/Client.php';
  26. /**
  27. * @see Zend_Json
  28. */
  29. require_once 'Zend/Json.php';
  30. /**
  31. * @see Zend_Oauth2
  32. */
  33. require_once 'Zend/Oauth2.php';
  34. /**
  35. * @category Zend
  36. * @package Zend_Service
  37. * @subpackage Twitter
  38. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  39. * @license http://framework.zend.com/license/new-bsd New BSD License
  40. */
  41. class Zend_Service_Facebook extends Zend_Rest_Client
  42. {
  43. /**
  44. *
  45. */
  46. const API_URL = 'https://graph.facebook.com/';
  47. /**
  48. *
  49. */
  50. const SEARCH_URI = 'search';
  51. /**
  52. *
  53. * @var booleen
  54. */
  55. protected $_connectionsIntropsection = false;
  56. /**
  57. *
  58. * @var string
  59. */
  60. protected $_appId;
  61. /**
  62. *
  63. * @var string
  64. */
  65. protected $_appSecret;
  66. /**
  67. * Local HTTP Client cloned from statically set client
  68. * @var Zend_Http_Client
  69. */
  70. protected $_localHttpClient = null;
  71. /**
  72. *
  73. * @var string
  74. */
  75. protected $_objectId = 'me';
  76. /**
  77. *
  78. * @var string
  79. */
  80. protected $_accessToken = null;
  81. /**
  82. *
  83. * @var mixed
  84. */
  85. protected $_objectFields = null;
  86. /**
  87. *
  88. * @var mixed
  89. */
  90. protected $_objectConnections = null;
  91. /**
  92. *
  93. * @var int
  94. */
  95. protected $_limit = null;
  96. /**
  97. *
  98. * @var int
  99. */
  100. protected $_offset = null;
  101. /**
  102. *
  103. * @var <type>
  104. */
  105. protected $_since = null;
  106. /**
  107. *
  108. * @var <type>
  109. */
  110. protected $_until = null;
  111. /**
  112. *
  113. * @var <type>
  114. */
  115. protected $_searchQuery = null;
  116. /**
  117. *
  118. * @var <type>
  119. */
  120. protected $_searchType = 'home';
  121. /**
  122. * Constructor
  123. *
  124. * @return void
  125. */
  126. public function __construct($options = null)
  127. {
  128. // if options are instance of zend config convert them to array
  129. if ($options instanceof Zend_Config) {
  130. $options = $options->toArray();
  131. }
  132. //Zend_Debug::dump($options);
  133. //
  134. if (is_array($options)) {
  135. $this->setOptions($options);
  136. }
  137. // setup http (rest) client
  138. $this->setLocalHttpClient(clone self::getHttpClient());
  139. $this->setUri(self::API_URL);
  140. $this->_localHttpClient->setHeaders('Accept-Charset', 'ISO-8859-1,utf-8');
  141. //Zend_Debug::dump($this->_localHttpClient);
  142. }
  143. /**
  144. * Set options
  145. *
  146. * @param $options
  147. * @return Zend_Service_Facebook
  148. */
  149. public function setOptions(array $options)
  150. {
  151. foreach ($options as $key => $value) {
  152. $method = 'set' . $key;
  153. if (method_exists($this, $method)) {
  154. $this->$method($value);
  155. }
  156. }
  157. return $this;
  158. }
  159. /**
  160. * Set local HTTP client as distinct from the static HTTP client
  161. * as inherited from Zend_Rest_Client.
  162. *
  163. * @param Zend_Http_Client $client
  164. * @return self
  165. */
  166. public function setLocalHttpClient(Zend_Http_Client $client)
  167. {
  168. $this->_localHttpClient = $client;
  169. return $this;
  170. }
  171. /**
  172. *
  173. * @return <type>
  174. */
  175. public function getLocalHttpClient()
  176. {
  177. return $this->_localHttpClient;
  178. }
  179. /**
  180. *
  181. * @param <type> $status
  182. * @return <type>
  183. */
  184. public function setConnectionsIntropsection($status)
  185. {
  186. $this->_connectionsIntropsection = (bool) $status;
  187. return $this;
  188. }
  189. /**
  190. *
  191. * @return <type>
  192. */
  193. public function getConnectionsIntropsection()
  194. {
  195. return $this->_connectionsIntropsection;
  196. }
  197. /**
  198. *
  199. * @param <type> $appId
  200. * @return <type>
  201. */
  202. public function setAppId($appId)
  203. {
  204. $this->_appId = $appId;
  205. //Zend_Debug::dump($this->_appId);
  206. return $this;
  207. }
  208. /**
  209. *
  210. * @return <type>
  211. */
  212. public function getAppId()
  213. {
  214. return $this->_appId;
  215. }
  216. /**
  217. *
  218. * @param <type> $apiSecret
  219. * @return <type>
  220. */
  221. public function setAppSecret($appSecret)
  222. {
  223. $this->_appSecret = $appSecret;
  224. return $this;
  225. }
  226. /**
  227. *
  228. * @return <type>
  229. */
  230. public function getAppSecret()
  231. {
  232. return $this->_appSecret;
  233. }
  234. /**
  235. *
  236. * @param <type> $apiSecret
  237. * @return <type>
  238. */
  239. public function setObjectId($objectId)
  240. {
  241. $this->_objectId = $objectId;
  242. return $this;
  243. }
  244. /**
  245. *
  246. * @return <type>
  247. */
  248. public function getObjectId()
  249. {
  250. return $this->_objectId;
  251. }
  252. /**
  253. *
  254. * @param <type> $apiSecret
  255. * @return <type>
  256. */
  257. public function setAccessToken($accessToken)
  258. {
  259. $this->_accessToken = $accessToken;
  260. return $this;
  261. }
  262. /**
  263. *
  264. * @return <type>
  265. */
  266. public function getAccessToken()
  267. {
  268. return $this->_accessToken;
  269. }
  270. /**
  271. *
  272. */
  273. public function clearAccessToken()
  274. {
  275. $this->_accessToken = null;
  276. }
  277. /**
  278. *
  279. */
  280. public function setObjectFields()
  281. {
  282. }
  283. /**
  284. *
  285. */
  286. public function getObjectFields()
  287. {
  288. return $this->_objectFields;
  289. }
  290. /**
  291. *
  292. */
  293. public function addObjectField()
  294. {
  295. }
  296. /**
  297. *
  298. */
  299. public function removeObjectField()
  300. {
  301. }
  302. /**
  303. *
  304. */
  305. public function addObjectFields()
  306. {
  307. }
  308. /**
  309. *
  310. */
  311. public function removeObjectFields()
  312. {
  313. }
  314. /**
  315. *
  316. */
  317. public function clearObjectFields()
  318. {
  319. $this->_objectFields = null;
  320. }
  321. /**
  322. *
  323. */
  324. public function setObjectConnections()
  325. {
  326. }
  327. /**
  328. *
  329. */
  330. public function getObjectConnections()
  331. {
  332. return $this->_objectConnections;
  333. }
  334. /**
  335. *
  336. */
  337. public function addObjectConnection()
  338. {
  339. }
  340. /**
  341. *
  342. */
  343. public function removeObjectConnection()
  344. {
  345. }
  346. /**
  347. *
  348. */
  349. public function addObjectConnections()
  350. {
  351. }
  352. /**
  353. *
  354. */
  355. public function removeObjectConnections()
  356. {
  357. }
  358. /**
  359. *
  360. */
  361. public function clearObjectConnections()
  362. {
  363. $this->_objectConnections = null;
  364. }
  365. /**
  366. *
  367. * @param int $limit
  368. * @return <type>
  369. */
  370. public function setLimit($limit)
  371. {
  372. $this->_limit = (int) $limit;
  373. return $this;
  374. }
  375. /**
  376. *
  377. * @return int
  378. */
  379. public function getLimit()
  380. {
  381. return $this->_limit;
  382. }
  383. /**
  384. *
  385. */
  386. public function clearLimit()
  387. {
  388. $this->_limit = null;
  389. }
  390. /**
  391. *
  392. * @param int $offset
  393. * @return <type>
  394. */
  395. public function setOffset($offset)
  396. {
  397. $this->_offset = (int) $offset;
  398. return $this;
  399. }
  400. /**
  401. *
  402. * @return int
  403. */
  404. public function getOffset()
  405. {
  406. return $this->_offset;
  407. }
  408. /**
  409. *
  410. */
  411. public function clearOffset()
  412. {
  413. $this->_offset = null;
  414. }
  415. /**
  416. *
  417. * @param mixed $since
  418. * @return <type>
  419. */
  420. public function setSince($since)
  421. {
  422. /*if (!is_numeric($since) && strtotime($since) === false) {
  423. require_once 'Zend/Service/Facebook/Exception.php';
  424. throw new Zend_Service_Facebook_Exception('wrong date / time fromat');
  425. }*/
  426. $this->_since = $since;
  427. return $this;
  428. }
  429. /**
  430. *
  431. * @return
  432. */
  433. public function getSince()
  434. {
  435. return $this->_since;
  436. }
  437. /**
  438. *
  439. */
  440. public function clearSince()
  441. {
  442. $this->_since = null;
  443. }
  444. /**
  445. *
  446. * @param mixed $until
  447. * @return <type>
  448. */
  449. public function setUntil($until)
  450. {
  451. if (!is_numeric($since) && strtotime($until) === false) {
  452. require_once 'Zend/Service/Facebook/Exception.php';
  453. throw new Zend_Service_Facebook_Exception('wrong date / time fromat');
  454. }
  455. $this->_until = $until;
  456. return $this;
  457. }
  458. /**
  459. *
  460. * @return
  461. */
  462. public function getUntil()
  463. {
  464. return $this->_until;
  465. }
  466. /**
  467. *
  468. */
  469. public function clearUntil()
  470. {
  471. $this->_until = null;
  472. }
  473. /**
  474. *
  475. * @param string $searchQuery
  476. * @return <type>
  477. */
  478. public function setSearchQuery($searchQuery)
  479. {
  480. $this->_searchQuery = $searchQuery;
  481. return $this;
  482. }
  483. /**
  484. *
  485. * @return <type>
  486. */
  487. public function getSearchQuery()
  488. {
  489. return $this->_searchQuery;
  490. }
  491. /**
  492. *
  493. * @param <type> $searchType
  494. * @return <type>
  495. */
  496. public function setSearchType($searchType)
  497. {
  498. $this->_searchType = $searchType;
  499. return $this;
  500. }
  501. /**
  502. *
  503. * @return <type>
  504. */
  505. public function getSearchType()
  506. {
  507. return $this->_searchType;
  508. }
  509. /**
  510. *
  511. * Performs a Facebook (open) graph query
  512. *
  513. * @param <type> $objectId
  514. * @param <type> $accessToken
  515. * @param <type> $objectConnections
  516. * @param <type> $objectFields
  517. * @param <type> $connectionsIntropsection
  518. * @param <type> $limit
  519. * @param <type> $offset
  520. * @param <type> $since
  521. * @param <type> $until
  522. * @return <type>
  523. */
  524. public function graphQuery($objectId = null, $accessToken = null, $objectConnections = null, $objectFields = null, $connectionsIntropsection = null, $limit = null, $offset = null, $since = null, $until = null)
  525. {
  526. // set basic path
  527. if (is_null($objectId)) $objectId = $this->getObjectId();
  528. $path = $objectId;
  529. // check if the query limit / offset / since / until are set, if true add them to the query
  530. if (is_null($limit)) $limit = $this->getLimit();
  531. if (is_null($offset)) $offset = $this->getOffset();
  532. if (is_null($since)) $since = $this->getSince();
  533. if (is_null($until)) $until = $this->getUntil();
  534. // prepare the query array
  535. $queryAndPathArray = $this->_prepareGraphQuery($objectFields, $objectConnections, $path, $limit, $offset, $since, $until);
  536. $query = $queryAndPathArray[0];
  537. $path = $queryAndPathArray[1];
  538. // check if accesstoken is available
  539. if (is_null($accessToken)) $accessToken = $this->_accessToken;
  540. if (!is_null($accessToken)) $query['access_token'] = $accessToken;
  541. // check if connectionsIntropsection was set and is set to true
  542. if (is_null($connectionsIntropsection)) $connectionsIntropsection = $this->_connectionsIntropsection;
  543. if (!is_null($connectionsIntropsection) && $connectionsIntropsection) $query['metadata'] = '1';
  544. //Zend_Debug::dump($path);
  545. //Zend_Debug::dump($query);
  546. //exit;
  547. // retrieve response
  548. $response = $this->_getResponse($path, $query);
  549. // check if response is not empty
  550. if (!is_null($response)) {
  551. $body = $response->getBody();
  552. $status = $response->getStatus();
  553. } else {
  554. require_once 'Zend/Service/Facebook/Exception.php';
  555. throw new Zend_Service_Facebook_Exception('the response we recieved is emtpy');
  556. }
  557. //Zend_Debug::dump($body, 'body');
  558. //exit;
  559. // convert json response into an array
  560. $responseAsArray = Zend_Json::decode($body);
  561. // if status code is different then 200 throw exception
  562. if ($status != '200') {
  563. require_once 'Zend/Oauth2/Exception.php';
  564. throw new Zend_Oauth2_Exception('we recieved an error ('.$status.') as response: '.$responseAsArray['error']['type'].' => '.$responseAsArray['error']['message']);
  565. }
  566. return $responseAsArray;
  567. }
  568. /**
  569. *
  570. * Performs a Facebook search query.
  571. *
  572. * @throws Zend_Http_Client_Exception
  573. *
  574. * @param <type> $searchType
  575. * @param <type> $searchQuery
  576. * @param <type> $accessToken
  577. * @return <type>
  578. */
  579. public function searchGraphQuery($searchQuery = null, $searchType = null, $accessToken = null)
  580. {
  581. // We support search for the following types of objects:
  582. // All public posts: https://graph.facebook.com/search?q=watermelon&type=post
  583. // People: https://graph.facebook.com/search?q=mark&type=user
  584. // Pages: https://graph.facebook.com/search?q=platform&type=page
  585. // Events: https://graph.facebook.com/search?q=conference&type=event
  586. // Groups: https://graph.facebook.com/search?q=programming&type=group
  587. // You can also search an individual user's News Feed, restricted to that
  588. // user's friends, by adding a q argument to the home connection URL:
  589. // News Feed: https://graph.facebook.com/me/home?q=facebook
  590. // build query array
  591. $query = array();
  592. $path = self::SEARCH_URI;
  593. // the search query parameter is required, check if its not null or
  594. // throw error
  595. if (is_null($searchQuery)) $searchQuery = $this->getSearchQuery();
  596. if (is_null($searchQuery)) {
  597. require_once 'Zend/Service/Facebook/Exception.php';
  598. throw new Zend_Service_Facebook_Exception('the search query parameter is required');
  599. } else {
  600. //$query['q'] = rawurlencode($searchQuery);
  601. $query['q'] = $searchQuery;
  602. }
  603. // check if search type is home, which it is by default, if its home
  604. // we have to use another search url
  605. if (is_null($searchType)) $searchType = $this->getSearchType();
  606. if ($searchType == 'home') {
  607. $path = 'me/home';
  608. } else {
  609. $query['type'] = $searchType;
  610. }
  611. // check if accesstoken is available
  612. if (is_null($accessToken)) $accessToken = $this->_accessToken;
  613. if (!is_null($accessToken)) $query['access_token'] = $accessToken;
  614. // retrieve response
  615. $response = $this->_getResponse($path, $query);
  616. // check if response is not empty
  617. if (!is_null($response)) {
  618. $body = $response->getBody();
  619. $status = $response->getStatus();
  620. } else {
  621. require_once 'Zend/Service/Facebook/Exception.php';
  622. throw new Zend_Service_Facebook_Exception('the response we recieved is emtpy');
  623. }
  624. //Zend_Debug::dump($body, 'body');
  625. //exit;
  626. // convert json response into an array
  627. $responseAsArray = Zend_Json::decode($body);
  628. // if status code is different then 200 throw exception
  629. if ($status != '200') {
  630. require_once 'Zend/Oauth2/Exception.php';
  631. throw new Zend_Oauth2_Exception('we recieved an error ('.$status.') as response: '.$responseAsArray['error']['type'].' => '.$responseAsArray['error']['message']);
  632. }
  633. return $responseAsArray;
  634. }
  635. /**
  636. *
  637. * @param <type> $objectFields
  638. * @param <type> $objectConnections
  639. * @param <type> $path
  640. * @param <type> $limit
  641. * @param <type> $offset
  642. * @param <type> $since
  643. * @param <type> $until
  644. * @return <type>
  645. */
  646. protected function _prepareGraphQuery($objectFields = null, $objectConnections = null, $path = '', $limit = null, $offset = null, $since = null, $until = null)
  647. {
  648. // build query array
  649. $query = array();
  650. // if the limit / offset / since / until is not null add it to query parameters
  651. if (!is_null($limit)) $query['limit'] = $limit;
  652. if (!is_null($offset) && !is_null($limit)) $query['offset'] = $offset;
  653. if (!is_null($since) && !is_null($limit)) $query['since'] = $since;
  654. if (!is_null($until) && !is_null($limit)) $query['until'] = $until;
  655. // if both are null return null
  656. if (is_null($objectFields) && is_null($objectConnections)) return array(null, $path);
  657. // if only connections are null return query with fields list
  658. if (!is_null($objectFields) && is_null($objectConnections)) {
  659. // check if fields got specified
  660. if (is_string($objectFields)) {
  661. $query['fields'] = $objectFields;
  662. } else {
  663. if (count($objectFields) === 1) {
  664. $query['fields'] = $objectFields[0];
  665. } elseif ((count($objectFields) > 1)) {
  666. $query['fields'] = implode(',', $objectFields);
  667. }
  668. }
  669. return array($query, $path);
  670. }
  671. // if only fields are null return query with connections list
  672. // strange behavior
  673. // fields and connections dont behave the same, you can mix them and then path the whole list as parameter
  674. // even if you pass multiple connections to facebook you can pass then as fields list
  675. // but if you only need to pass one connection you must add it to the path
  676. // a single field is ok if you pass it in the fields query but not a single connection
  677. if (is_null($objectFields) && !is_null($objectConnections)) {
  678. // check if fields got specified
  679. if (is_string($objectConnections)) {
  680. $path .= '/'.$objectConnections;
  681. } else {
  682. if (count($objectConnections) === 1) {
  683. $path .= '/'.$objectConnections[0];
  684. } elseif ((count($objectConnections) > 1)) {
  685. $query['fields'] = implode(',', $objectConnections);
  686. }
  687. }
  688. return array($query, $path);
  689. }
  690. // if none is null return query with connections and fields list
  691. if (!is_null($objectFields) && !is_null($objectConnections)) {
  692. $fieldsAndConnections = array();
  693. if (is_string($objectFields)) $fieldsAndConnections[] = $objectFields;
  694. if (is_string($objectConnections)) $fieldsAndConnections[] = $objectConnections;
  695. if (is_array($objectFields)) $fieldsAndConnections = array_merge($fieldsAndConnections, $objectFields);
  696. if (is_array($objectConnections)) $fieldsAndConnections = array_merge($fieldsAndConnections, $objectConnections);
  697. $query['fields'] = implode(',', $fieldsAndConnections);
  698. return array($query, $path);
  699. }
  700. }
  701. /**
  702. * Performs an HTTP GET request to the $path.
  703. *
  704. * @param string $path
  705. * @param array $query Array of GET parameters
  706. * @throws Zend_Http_Client_Exception
  707. * @return Zend_Http_Response
  708. */
  709. protected function _getResponse($path, array $query = null)
  710. {
  711. // Get the URI object and configure it
  712. if (!$this->_uri instanceof Zend_Uri_Http) {
  713. require_once 'Zend/Rest/Client/Exception.php';
  714. throw new Zend_Rest_Client_Exception('URI object must be set before performing call');
  715. }
  716. $uri = $this->_uri->getUri();
  717. if ($path[0] != '/') {
  718. $path = '/' . $path;
  719. }
  720. $this->_uri->setPath($path);
  721. /**
  722. * Get the HTTP client and configure it for the endpoint URI. Do this each time
  723. * because the Zend_Http_Client instance is shared among all Zend_Service_Abstract subclasses.
  724. */
  725. $this->_localHttpClient ->resetParameters()
  726. ->setUri($this->_uri)
  727. ->setParameterGet($query);
  728. return $this->_localHttpClient->request('GET');
  729. }
  730. }