]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/FacebookSSO/lib/facebookclient.php
Merge branch '0.9.x' into facebook-upgrade
[quix0rs-gnu-social.git] / plugins / FacebookSSO / lib / facebookclient.php
1 <?php
2 /**
3  * StatusNet, the distributed open-source microblogging tool
4  *
5  * Class for communicating with Facebook
6  *
7  * PHP version 5
8  *
9  * LICENCE: This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU Affero General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU Affero General Public License for more details.
18  *
19  * You should have received a copy of the GNU Affero General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  * @category  Plugin
23  * @package   StatusNet
24  * @author    Craig Andrews <candrews@integralblue.com>
25  * @author    Zach Copley <zach@status.net>
26  * @copyright 2009-2010 StatusNet, Inc.
27  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
28  * @link      http://status.net/
29  */
30
31 if (!defined('STATUSNET')) {
32     exit(1);
33 }
34
35 /**
36  * Class for communication with Facebook
37  *
38  * @category Plugin
39  * @package  StatusNet
40  * @author   Zach Copley <zach@status.net>
41  * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
42  * @link     http://status.net/
43  */
44 class Facebookclient
45 {
46     protected $facebook      = null; // Facebook Graph client obj
47     protected $flink         = null; // Foreign_link StatusNet -> Facebook
48     protected $notice        = null; // The user's notice
49     protected $user          = null; // Sender of the notice
50
51     function __construct($notice)
52     {
53         $this->facebook = self::getFacebook();
54         $this->notice   = $notice;
55
56         $this->flink = Foreign_link::getByUserID(
57             $notice->profile_id,
58             FACEBOOK_SERVICE
59         );
60
61         $this->user = $this->flink->getUser();
62     }
63
64     /*
65      * Get an instance of the Facebook Graph SDK object
66      *
67      * @param string $appId     Application
68      * @param string $secret    Facebook API secret
69      *
70      * @return Facebook A Facebook SDK obj
71      */
72     static function getFacebook($appId = null, $secret = null)
73     {
74         // Check defaults and configuration for application ID and secret
75         if (empty($appId)) {
76             $appId = common_config('facebook', 'appid');
77         }
78
79         if (empty($secret)) {
80             $secret = common_config('facebook', 'secret');
81         }
82
83         // If there's no app ID and secret set in the local config, look
84         // for a global one
85         if (empty($appId) || empty($secret)) {
86             $appId  = common_config('facebook', 'global_appid');
87             $secret = common_config('facebook', 'global_secret');
88         }
89
90         return new Facebook(
91             array(
92                'appId'  => $appId,
93                'secret' => $secret,
94                'cookie' => true
95             )
96         );
97     }
98
99     /*
100      * Broadcast a notice to Facebook
101      *
102      * @param Notice $notice    the notice to send
103      */
104     static function facebookBroadcastNotice($notice)
105     {
106         common_debug('Facebook broadcast');
107         $client = new Facebookclient($notice);
108         return $client->sendNotice();
109     }
110
111     /*
112      * Should the notice go to Facebook?
113      */
114     function isFacebookBound() {
115
116         if (empty($this->flink)) {
117             common_log(
118                 LOG_WARN,
119                 sprintf(
120                     "No Foreign_link to Facebook for the author of notice %d.",
121                     $this->notice->id
122                 ),
123                 __FILE__
124             );
125             return false;
126         }
127
128         // Avoid a loop
129         if ($this->notice->source == 'Facebook') {
130             common_log(
131                 LOG_INFO,
132                 sprintf(
133                     'Skipping notice %d because its source is Facebook.',
134                     $this->notice->id
135                 ),
136                 __FILE__
137             );
138             return false;
139         }
140
141         // If the user does not want to broadcast to Facebook, move along
142         if (!($this->flink->noticesync & FOREIGN_NOTICE_SEND == FOREIGN_NOTICE_SEND)) {
143             common_log(
144                 LOG_INFO,
145                 sprintf(
146                     'Skipping notice %d because user has FOREIGN_NOTICE_SEND bit off.',
147                     $this->notice->id
148                 ),
149                 __FILE__
150             );
151             return false;
152         }
153
154         // If it's not a reply, or if the user WANTS to send @-replies,
155         // then, yeah, it can go to Facebook.
156         if (!preg_match('/@[a-zA-Z0-9_]{1,15}\b/u', $this->notice->content) ||
157             ($this->flink->noticesync & FOREIGN_NOTICE_SEND_REPLY)) {
158             return true;
159         }
160
161         return false;
162     }
163
164     /*
165      * Determine whether we should send this notice using the Graph API or the
166      * old REST API and then dispatch
167      */
168     function sendNotice()
169     {
170         // If there's nothing in the credentials field try to send via
171         // the Old Rest API
172
173         if ($this->isFacebookBound()) {
174             common_debug("notice is facebook bound", __FILE__);
175             if (empty($this->flink->credentials)) {
176                 return $this->sendOldRest();
177             } else {
178
179                 // Otherwise we most likely have an access token
180                 return $this->sendGraph();
181             }
182
183         } else {
184             common_debug(
185                 sprintf(
186                     "Skipping notice %d - not bound for Facebook",
187                     $this->notice->id,
188                     __FILE__
189                 )
190             );
191         }
192     }
193
194     /*
195      * Send a notice to Facebook using the Graph API
196      */
197     function sendGraph()
198     {
199         try {
200
201             $fbuid = $this->flink->foreign_id;
202
203             common_debug(
204                 sprintf(
205                     "Attempting use Graph API to post notice %d as a stream item for %s (%d), fbuid %s",
206                     $this->notice->id,
207                     $this->user->nickname,
208                     $this->user->id,
209                     $fbuid
210                 ),
211                 __FILE__
212             );
213
214             $params = array(
215                 'access_token' => $this->flink->credentials,
216                 // XXX: Need to worrry about length of the message?
217                 'message'      => $this->notice->content
218             );
219
220             $attachments = $this->notice->attachments();
221
222             if (!empty($attachments)) {
223
224                 // We can only send one attachment with the Graph API :(
225
226                 $first = array_shift($attachments);
227
228                 if (substr($first->mimetype, 0, 6) == 'image/'
229                     || in_array(
230                         $first->mimetype,
231                         array('application/x-shockwave-flash', 'audio/mpeg' ))) {
232
233                    $params['picture'] = $first->url;
234                    $params['caption'] = 'Click for full size';
235                    $params['source']  = $first->url;
236                 }
237
238             }
239
240             $result = $this->facebook->api(
241                 sprintf('/%s/feed', $fbuid), 'post', $params
242             );
243
244             // Save a mapping
245             Notice_to_item::saveNew($this->notice->id, $result['id']);
246
247             common_log(
248                 LOG_INFO,
249                 sprintf(
250                     "Posted notice %d as a stream item for %s (%d), fbuid %s",
251                     $this->notice->id,
252                     $this->user->nickname,
253                     $this->user->id,
254                     $fbuid
255                 ),
256                 __FILE__
257             );
258
259         } catch (FacebookApiException $e) {
260             return $this->handleFacebookError($e);
261         }
262
263         return true;
264     }
265
266     /*
267      * Send a notice to Facebook using the deprecated Old REST API. We need this
268      * for backwards compatibility. Users who signed up for Facebook bridging
269      * using the old Facebook Canvas application do not have an OAuth 2.0
270      * access token.
271      */
272     function sendOldRest()
273     {
274         try {
275
276             $canPublish = $this->checkPermission('publish_stream');
277             $canUpdate  = $this->checkPermission('status_update');
278
279             // We prefer to use stream.publish, because it can handle
280             // attachments and returns the ID of the published item
281
282             if ($canPublish == 1) {
283                 $this->restPublishStream();
284             } else if ($canUpdate == 1) {
285                 // as a last resort we can just update the user's "status"
286                 $this->restStatusUpdate();
287             } else {
288
289                 $msg = 'Not sending notice %d to Facebook because user %s '
290                      . '(%d), fbuid %s,  does not have \'status_update\' '
291                      . 'or \'publish_stream\' permission.';
292
293                 common_log(
294                     LOG_WARNING,
295                     sprintf(
296                         $msg,
297                         $this->notice->id,
298                         $this->user->nickname,
299                         $this->user->id,
300                         $this->flink->foreign_id
301                     ),
302                     __FILE__
303                 );
304             }
305
306         } catch (FacebookApiException $e) {
307             return $this->handleFacebookError($e);
308         }
309
310         return true;
311     }
312
313     /*
314      * Query Facebook to to see if a user has permission
315      *
316      *
317      *
318      * @param $permission the permission to check for - must be either
319      *                    public_stream or status_update
320      *
321      * @return boolean result
322      */
323     function checkPermission($permission)
324     {
325         if (!in_array($permission, array('publish_stream', 'status_update'))) {
326              throw new ServerException("No such permission!");
327         }
328
329         $fbuid = $this->flink->foreign_id;
330
331         common_debug(
332             sprintf(
333                 'Checking for %s permission for user %s (%d), fbuid %s',
334                 $permission,
335                 $this->user->nickname,
336                 $this->user->id,
337                 $fbuid
338             ),
339             __FILE__
340         );
341
342         $hasPermission = $this->facebook->api(
343             array(
344                 'method'   => 'users.hasAppPermission',
345                 'ext_perm' => $permission,
346                 'uid'      => $fbuid
347             )
348         );
349
350         if ($hasPermission == 1) {
351
352             common_debug(
353                 sprintf(
354                     '%s (%d), fbuid %s has %s permission',
355                     $permission,
356                     $this->user->nickname,
357                     $this->user->id,
358                     $fbuid
359                 ),
360                 __FILE__
361             );
362
363             return true;
364
365         } else {
366
367             $logMsg = '%s (%d), fbuid $fbuid does NOT have %s permission.'
368                     . 'Facebook returned: %s';
369
370             common_debug(
371                 sprintf(
372                     $logMsg,
373                     $this->user->nickname,
374                     $this->user->id,
375                     $permission,
376                     $fbuid,
377                     var_export($result, true)
378                 ),
379                 __FILE__
380             );
381
382             return false;
383
384         }
385     }
386
387     /*
388      * Handle a Facebook API Exception
389      *
390      * @param FacebookApiException $e the exception
391      *
392      */
393     function handleFacebookError($e)
394     {
395         $fbuid  = $this->flink->foreign_id;
396         $errmsg = $e->getMessage();
397         $code   = $e->getCode();
398
399         // The Facebook PHP SDK seems to always set the code attribute
400         // of the Exception to 0; they put the real error code in
401         // the message. Gar!
402         if ($code == 0) {
403             preg_match('/^\(#(?<code>\d+)\)/', $errmsg, $matches);
404             $code = $matches['code'];
405         }
406
407         // XXX: Check for any others?
408         switch($code) {
409          case 100: // Invalid parameter
410             $msg = 'Facebook claims notice %d was posted with an invalid '
411                  . 'parameter (error code 100 - %s) Notice details: '
412                  . '[nickname=%s, user id=%d, fbuid=%d, content="%s"]. '
413                  . 'Dequeing.';
414             common_log(
415                 LOG_ERR, sprintf(
416                     $msg,
417                     $this->notice->id,
418                     $errmsg,
419                     $this->user->nickname,
420                     $this->user->id,
421                     $fbuid,
422                     $this->notice->content
423                 ),
424                 __FILE__
425             );
426             return true;
427             break;
428          case 200: // Permissions error
429          case 250: // Updating status requires the extended permission status_update
430             $this->disconnect();
431             return true; // dequeue
432             break;
433          case 341: // Feed action request limit reached
434                 $msg = '%s (userid=%d, fbuid=%d) has exceeded his/her limit '
435                      . 'for posting notices to Facebook today. Dequeuing '
436                      . 'notice %d';
437                 common_log(
438                     LOG_INFO, sprintf(
439                         $msg,
440                         $user->nickname,
441                         $user->id,
442                         $fbuid,
443                         $this->notice->id
444                     ),
445                     __FILE__
446                 );
447             // @fixme: We want to rety at a later time when the throttling has expired
448             // instead of just giving up.
449             return true;
450             break;
451          default:
452             $msg = 'Facebook returned an error we don\'t know how to deal with '
453                  . 'when posting notice %d. Error code: %d, error message: "%s"'
454                  . ' Notice details: [nickname=%s, user id=%d, fbuid=%d, '
455                  . 'notice content="%s"]. Dequeing.';
456             common_log(
457                 LOG_ERR, sprintf(
458                     $msg,
459                     $this->notice->id,
460                     $code,
461                     $errmsg,
462                     $this->user->nickname,
463                     $this->user->id,
464                     $fbuid,
465                     $this->notice->content
466                 ),
467                 __FILE__
468             );
469             return true; // dequeue
470             break;
471         }
472     }
473
474     /*
475      * Publish a notice to Facebook as a status update
476      *
477      * This is the least preferable way to send a notice to Facebook because
478      * it doesn't support attachments and the API method doesn't return
479      * the ID of the post on Facebook.
480      *
481      */
482     function restStatusUpdate()
483     {
484         $fbuid = $this->flink->foreign_id;
485
486         common_debug(
487             sprintf(
488                 "Attempting to post notice %d as a status update for %s (%d), fbuid %s",
489                 $this->notice->id,
490                 $this->user->nickname,
491                 $this->user->id,
492                 $fbuid
493             ),
494             __FILE__
495         );
496
497         $result = $this->facebook->api(
498             array(
499                 'method'               => 'users.setStatus',
500                 'status'               => $this->formatMessage(),
501                 'status_includes_verb' => true,
502                 'uid'                  => $fbuid
503             )
504         );
505
506         if ($result == 1) { // 1 is success
507
508             common_log(
509                 LOG_INFO,
510                 sprintf(
511                     "Posted notice %s as a status update for %s (%d), fbuid %s",
512                     $this->notice->id,
513                     $this->user->nickname,
514                     $this->user->id,
515                     $fbuid
516                 ),
517                 __FILE__
518             );
519
520             // There is no item ID returned for status update so we can't
521             // save a Notice_to_item mapping
522
523         } else {
524
525             $msg = sprintf(
526                 "Error posting notice %s as a status update for %s (%d), fbuid %s - error code: %s",
527                 $this->notice->id,
528                 $this->user->nickname,
529                 $this->user->id,
530                 $fbuid,
531                 $result // will contain 0, or an error
532             );
533
534             throw new FacebookApiException($msg, $result);
535         }
536     }
537
538     /*
539      * Publish a notice to a Facebook user's stream using the old REST API
540      */
541     function restPublishStream()
542     {
543         $fbuid = $this->flink->foreign_id;
544
545         common_debug(
546             sprintf(
547                 'Attempting to post notice %d as stream item for %s (%d) fbuid %s',
548                 $this->notice->id,
549                 $this->user->nickname,
550                 $this->user->id,
551                 $fbuid
552             ),
553             __FILE__
554         );
555
556         $fbattachment = $this->formatAttachments();
557
558         $result = $this->facebook->api(
559             array(
560                 'method'     => 'stream.publish',
561                 'message'    => $this->formatMessage(),
562                 'attachment' => $fbattachment,
563                 'uid'        => $fbuid
564             )
565         );
566
567         if (!empty($result)) { // result will contain the item ID
568
569             // Save a mapping
570             Notice_to_item::saveNew($this->notice->id, $result);
571
572             common_log(
573                 LOG_INFO,
574                 sprintf(
575                     'Posted notice %d as a %s for %s (%d), fbuid %s',
576                     $this->notice->id,
577                     empty($fbattachment) ? 'stream item' : 'stream item with attachment',
578                     $this->user->nickname,
579                     $this->user->id,
580                     $fbuid
581                 ),
582                 __FILE__
583             );
584
585         } else {
586
587             $msg = sprintf(
588                 'Could not post notice %d as a %s for %s (%d), fbuid %s - error code: %s',
589                 $this->notice->id,
590                 empty($fbattachment) ? 'stream item' : 'stream item with attachment',
591                 $this->user->nickname,
592                 $this->user->id,
593                 $result, // result will contain an error code
594                 $fbuid
595             );
596
597             throw new FacebookApiException($msg, $result);
598         }
599     }
600
601     /*
602      * Format the text message of a stream item so it's appropriate for
603      * sending to Facebook. If the notice is too long, truncate it, and
604      * add a linkback to the original notice at the end.
605      *
606      * @return String $txt the formated message
607      */
608     function formatMessage()
609     {
610         // Start with the plaintext source of this notice...
611         $txt = $this->notice->content;
612
613         // Facebook has a 420-char hardcoded max.
614         if (mb_strlen($statustxt) > 420) {
615             $noticeUrl = common_shorten_url($this->notice->uri);
616             $urlLen = mb_strlen($noticeUrl);
617             $txt = mb_substr($statustxt, 0, 420 - ($urlLen + 3)) . ' â€¦ ' . $noticeUrl;
618         }
619
620         return $txt;
621     }
622
623     /*
624      * Format attachments for the old REST API stream.publish method
625      *
626      * Note: Old REST API supports multiple attachments per post
627      *
628      */
629     function formatAttachments()
630     {
631         $attachments = $this->notice->attachments();
632
633         $fbattachment          = array();
634         $fbattachment['media'] = array();
635
636         foreach($attachments as $attachment)
637         {
638             if($enclosure = $attachment->getEnclosure()){
639                 $fbmedia = $this->getFacebookMedia($enclosure);
640             }else{
641                 $fbmedia = $this->getFacebookMedia($attachment);
642             }
643             if($fbmedia){
644                 $fbattachment['media'][]=$fbmedia;
645             }else{
646                 $fbattachment['name'] = ($attachment->title ?
647                                       $attachment->title : $attachment->url);
648                 $fbattachment['href'] = $attachment->url;
649             }
650         }
651         if(count($fbattachment['media'])>0){
652             unset($fbattachment['name']);
653             unset($fbattachment['href']);
654         }
655         return $fbattachment;
656     }
657
658     /**
659      * given a File objects, returns an associative array suitable for Facebook media
660      */
661     function getFacebookMedia($attachment)
662     {
663         $fbmedia    = array();
664
665         if (strncmp($attachment->mimetype, 'image/', strlen('image/')) == 0) {
666             $fbmedia['type']         = 'image';
667             $fbmedia['src']          = $attachment->url;
668             $fbmedia['href']         = $attachment->url;
669         } else if ($attachment->mimetype == 'audio/mpeg') {
670             $fbmedia['type']         = 'mp3';
671             $fbmedia['src']          = $attachment->url;
672         }else if ($attachment->mimetype == 'application/x-shockwave-flash') {
673             $fbmedia['type']         = 'flash';
674
675             // http://wiki.developers.facebook.com/index.php/Attachment_%28Streams%29
676             // says that imgsrc is required... but we have no value to put in it
677             // $fbmedia['imgsrc']='';
678
679             $fbmedia['swfsrc']       = $attachment->url;
680         }else{
681             return false;
682         }
683         return $fbmedia;
684     }
685
686     /*
687      * Disconnect a user from Facebook by deleting his Foreign_link.
688      * Notifies the user his account has been disconnected by email.
689      */
690     function disconnect()
691     {
692         $fbuid = $this->flink->foreign_id;
693
694         common_log(
695             LOG_INFO,
696             sprintf(
697                 'Removing Facebook link for %s (%d), fbuid %s',
698                 $this->user->nickname,
699                 $this->user->id,
700                 $fbuid
701             ),
702             __FILE__
703         );
704
705         $result = $this->flink->delete();
706
707         if (empty($result)) {
708             common_log(
709                 LOG_ERR,
710                 sprintf(
711                     'Could not remove Facebook link for %s (%d), fbuid %s',
712                     $this->user->nickname,
713                     $this->user->id,
714                     $fbuid
715                 ),
716                 __FILE__
717             );
718             common_log_db_error($flink, 'DELETE', __FILE__);
719         }
720
721         // Notify the user that we are removing their Facebook link
722
723         $result = $this->mailFacebookDisconnect();
724
725         if (!$result) {
726
727             $msg = 'Unable to send email to notify %s (%d), fbuid %s '
728                  . 'about his/her Facebook link being removed.';
729
730             common_log(
731                 LOG_WARNING,
732                 sprintf(
733                     $msg,
734                     $this->user->nickname,
735                     $this->user->id,
736                     $fbuid
737                 ),
738                 __FILE__
739             );
740         }
741     }
742
743     /**
744      * Send a mail message to notify a user that her Facebook link
745      * has been terminated.
746      *
747      * @return boolean success flag
748      */
749     function mailFacebookDisconnect()
750     {
751         $profile = $this->user->getProfile();
752
753         $siteName = common_config('site', 'name');
754
755         common_switch_locale($this->user->language);
756
757         $subject = _m('Your Facebook connection has been removed');
758
759         $msg = <<<BODY
760 Hi %1$s,
761
762 We're sorry to inform you we are unable to publish your notice to
763 Facebook, and have removed the connection between your %2$s account and
764 Facebook.
765
766 This may have happened because you have removed permission for %2$s
767 to post on your behalf, or perhaps you have deactivated your Facebook
768 account. You can reconnect your %s account to Facebook at any time by
769 logging in with Facebook again.
770
771 Sincerely,
772
773 %2$s
774 BODY;
775         $body = sprintf(
776             _m($msg),
777             $this->user->nickname,
778             $siteName
779         );
780
781         common_switch_locale();
782
783         return mail_to_user($this->user, $subject, $body);
784     }
785
786     /*
787      * Check to see if we have a mapping to a copy of this notice
788      * on Facebook
789      *
790      * @param Notice $notice the notice to check
791      *
792      * @return mixed null if it can't find one, or the id of the Facebook
793      *               stream item
794      */
795     static function facebookStatusId($notice)
796     {
797         $n2i = Notice_to_item::staticGet('notice_id', $notice->id);
798
799         if (empty($n2i)) {
800             return null;
801         } else {
802             return $n2i->item_id;
803         }
804     }
805
806     /*
807      * Save a Foreign_user record of a Facebook user
808      *
809      * @param object $fbuser a Facebook Graph API user obj
810      *                       See: http://developers.facebook.com/docs/reference/api/user
811      * @return mixed $result Id or key
812      *
813      */
814     static function addFacebookUser($fbuser)
815     {
816         // remove any existing, possibly outdated, record
817         $luser = Foreign_user::getForeignUser($fbuser['id'], FACEBOOK_SERVICE);
818
819         if (!empty($luser)) {
820
821             $result = $luser->delete();
822
823             if ($result != false) {
824                 common_log(
825                     LOG_INFO,
826                     sprintf(
827                         'Removed old Facebook user: %s, fbuid %d',
828                         $fbuid['name'],
829                         $fbuid['id']
830                     ),
831                     __FILE__
832                 );
833             }
834         }
835
836         $fuser = new Foreign_user();
837
838         $fuser->nickname = $fbuser['name'];
839         $fuser->uri      = $fbuser['link'];
840         $fuser->id       = $fbuser['id'];
841         $fuser->service  = FACEBOOK_SERVICE;
842         $fuser->created  = common_sql_now();
843
844         $result = $fuser->insert();
845
846         if (empty($result)) {
847             common_log(
848                 LOG_WARNING,
849                     sprintf(
850                         'Failed to add new Facebook user: %s, fbuid %d',
851                         $fbuser['name'],
852                         $fbuser['id']
853                     ),
854                     __FILE__
855             );
856
857             common_log_db_error($fuser, 'INSERT', __FILE__);
858         } else {
859             common_log(
860                 LOG_INFO,
861                 sprintf(
862                     'Added new Facebook user: %s, fbuid %d',
863                     $fbuser['name'],
864                     $fbuser['id']
865                 ),
866                 __FILE__
867             );
868         }
869
870         return $result;
871     }
872
873     /*
874      * Remove an item from a Facebook user's feed if we have a mapping
875      * for it.
876      */
877     function streamRemove()
878     {
879         $n2i = Notice_to_item::staticGet('notice_id', $this->notice->id);
880
881         if (!empty($this->flink) && !empty($n2i)) {
882
883             $result = $this->facebook->api(
884                 array(
885                     'method'  => 'stream.remove',
886                     'post_id' => $n2i->item_id,
887                     'uid'     => $this->flink->foreign_id
888                 )
889             );
890
891             if (!empty($result) && result == true) {
892
893                 common_log(
894                   LOG_INFO,
895                     sprintf(
896                         'Deleted Facebook item: %s for %s (%d), fbuid %d',
897                         $n2i->item_id,
898                         $this->user->nickname,
899                         $this->user->id,
900                         $this->flink->foreign_id
901                     ),
902                     __FILE__
903                 );
904
905                 $n2i->delete();
906
907             } else {
908
909                 common_log(
910                   LOG_WARNING,
911                     sprintf(
912                         'Could not deleted Facebook item: %s for %s (%d), fbuid %d',
913                         $n2i->item_id,
914                         $this->user->nickname,
915                         $this->user->id,
916                         $this->flink->foreign_id
917                     ),
918                     __FILE__
919                 );
920             }
921         }
922     }
923
924     /*
925      * Like an item in a Facebook user's feed if we have a mapping
926      * for it.
927      */
928     function like()
929     {
930         $n2i = Notice_to_item::staticGet('notice_id', $this->notice->id);
931
932         if (!empty($this->flink) && !empty($n2i)) {
933
934             $result = $this->facebook->api(
935                 array(
936                     'method'  => 'stream.addlike',
937                     'post_id' => $n2i->item_id,
938                     'uid'     => $this->flink->foreign_id
939                 )
940             );
941
942             if (!empty($result) && result == true) {
943
944                 common_log(
945                   LOG_INFO,
946                     sprintf(
947                         'Added like for item: %s for %s (%d), fbuid %d',
948                         $n2i->item_id,
949                         $this->user->nickname,
950                         $this->user->id,
951                         $this->flink->foreign_id
952                     ),
953                     __FILE__
954                 );
955
956             } else {
957
958                 common_log(
959                   LOG_WARNING,
960                     sprintf(
961                         'Could not like Facebook item: %s for %s (%d), fbuid %d',
962                         $n2i->item_id,
963                         $this->user->nickname,
964                         $this->user->id,
965                         $this->flink->foreign_id
966                     ),
967                     __FILE__
968                 );
969             }
970         }
971     }
972
973     /*
974      * Unlike an item in a Facebook user's feed if we have a mapping
975      * for it.
976      */
977     function unLike()
978     {
979         $n2i = Notice_to_item::staticGet('notice_id', $this->notice->id);
980
981         if (!empty($this->flink) && !empty($n2i)) {
982
983             $result = $this->facebook->api(
984                 array(
985                     'method'  => 'stream.removeLike',
986                     'post_id' => $n2i->item_id,
987                     'uid'     => $this->flink->foreign_id
988                 )
989             );
990
991             if (!empty($result) && result == true) {
992
993                 common_log(
994                   LOG_INFO,
995                     sprintf(
996                         'Removed like for item: %s for %s (%d), fbuid %d',
997                         $n2i->item_id,
998                         $this->user->nickname,
999                         $this->user->id,
1000                         $this->flink->foreign_id
1001                     ),
1002                     __FILE__
1003                 );
1004
1005             } else {
1006
1007                 common_log(
1008                   LOG_WARNING,
1009                     sprintf(
1010                         'Could not remove like for Facebook item: %s for %s (%d), fbuid %d',
1011                         $n2i->item_id,
1012                         $this->user->nickname,
1013                         $this->user->id,
1014                         $this->flink->foreign_id
1015                     ),
1016                     __FILE__
1017                 );
1018             }
1019         }
1020     }
1021
1022 }