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