...du verbe Drupaler (1er groupe)

Envoyer une invitation Request 2.0 à ses amis Facebook sur son site Drupal

10. Avril 2012 - 9:45 -- Thomas
Pré-requis :
Cette article s'adresse à des développeur qui ont une bonne connaissance en Drupal et en développement web tout court. Si rien de cette article ne vous parle nous vous invitons à utilisez simplement le module Drupal For Facebook.

Vous le savez sûrement déjà si vous êtes tombés sur cette article, le FBML est devenus déprécié (même si il doit l'être qu'à partir du 1er juin 20212), et l'une des fonctionnalités directement impactée, est l'invitation d'amis.
En effet, le module Drupal For Facebook inclut un module, FB friend, qui offre la possibilité d'inviter ses amis Facebook en construisant du FBML. Le problème est qu'aujourd'hui le comportement de cette requêtes est devenus instables (notamment le lien qui apparaît sur Facebook n'a pas d'effet). Vous pouvez toujours tester cette fonctionnalité sur http://www.drupalforfacebook.org
Vous pouvez consultez la documentation sur cette request 2.0 là:
http://developers.facebook.com/docs/reference/dialogs/friends/
Bien que nous n'utilisons pas la form gnérée par le module FB friends, nous utilisons tout de même Drupal For Facebook pour gérer l'application Facebook et son module FB Friend pour gérer les invitations en BD. Pour savoir comment l'installer rendez vous  sur http://drupalons.fr/implémenter-facebook-avec-drupal-6
L'une des problématique de cette nouvelle méthode est qu'elle oblige l'utilisation de canvas page (Iframe de votre site dans Facebook). Comprenez donc qu'une redirection après l'invitation vers votre site n'est pas réalisable "dans les règles".
La seconde problématique, qui découle de la première, étant donné que le canvas est obligatoire, et que Facebook a décrété que tout canvas page devrait être hébergé sur un domaine sécurisé (avec certificat SSL), il vous faudra un HTTPS. Quoi? Mais comment? Mais pourquoi? Et oui cette politique étant très contraignante, surtout pour des développeurs, Facebook a tout de même mis en place un service d'hébergement d'application notamment avec certificat SSL.
Pour son utilisation rendez-vous sur : http://drupalons.fr/contourner-lhttps-obligatoire-pour-les-applications-facebook

Entrons dans le vif du sujet :
Le principe est assez simple, on réalise un simple lien qui va appeler l'api Facebook en via du JavaScript.
On aura un callback AJAX qui se chargera lui d'exclure les ID des utilisateurs Facebook que l'on ne veut pas (ceux que l'utilisateur voit et invite).

Le hook menu qui déclare le callback AJAX:
/*
* Implementation of Hook_menu
*/
function module_facebook_menu(){
  
  //Callback ajax to return the Facebook ID's wich must be exclude
    $items['fb-invite/exclud_id'] = array(
            'page callback' => 'exclud_id_facebook',
       'page arguments' => array(1),
        'access arguments' => array('access content'),
            'type' => MENU_CALLBACK,
      );
    return $items;
  }
La fonction callback AJAX :

/* Implementation of AJAXPage_callback()
 * Fonction qui renvoi en format json les id facebook à exclure.
 *
*/  
  
function exclud_id_facebook(){
  //Si on est pas sur un appel js
  if (!$_POST['from_js'] && $_GET['example_token'] == drupal_get_token()) 
    {
    return t('Activer le javascript pour pouvoir inviter vos amis.');
    }
  elseif ($_POST['from_js'] && $_POST['example_token'] == drupal_get_token()) 
    {
    global $_fb, $_fb_app;
    $fbu = fb_facebook_user();
    if (!$fbu)
      {
      drupal_json(t('erreur de connexion Facebook'));
      exit;
      }
    // Exclude users who have already installed. Select the member's Facebook who have already the application
    $rs = fb_fql_query($_fb, "SELECT uid FROM user WHERE has_added_app=1 and uid IN (SELECT uid2 FROM friend WHERE uid1 = $fbu)"); // FQL not SQL, no {curly_brackets}
    //Select the memeber's who are alaredy mapped on our site
    $res=db_query("SELECT fbu FROM {fb_user} WHERE uid IS NOT NULL AND fbu IS NOT NULL ");  
    $alreadyRegister=array();
    while($result=db_fetch_array($res))
      $alreadyRegister[]=$result['fbu'];  
    $exclude_ids = array();
    // Build an delimited list of users...
    if ($rs) 
      {
      foreach ($rs as $data) 
        {
        //If the user has already application and he is already register on our site, we add him on exlude id list
        if(in_array($data["uid"],$alreadyRegister))
          $exclude_ids[] = $data["uid"];
        }
      }
    // Set the text/javascript headers and
    // return the response in JSON format.
    drupal_json($exclude_ids);
    exit;
    }
  else 
    {
    drupal_json(t('Page not found'));
    exit;
    }
  }
Enfin le JavaScript qui va réaliser la pop-up d'invitation Facebook ainsi que l'appel AJAX.

Javascipt :
 function requestCallback(response) {

    if (response && !response.error) {
      window.location.href='htttp://monsite.com/fb_friend/submit/module/fb_friend_invite_app/delta/fb_friend_invite_app/next/user/me/invites/fb-invite?ids='+serialize(response.to); 
   
    }
  }
Drupal.behaviors.ppFacebook = function(context) {
  var fbInvite = $('#fb-invite-buton');
	fbInvite.click(function(event) 
    { 
    //Envlève le comportement du bouton car sinon il est lancé plusieurs fois
    fbInvite.unbind('click');
		//bind le comportement ajax du callback de la page
    event.preventDefault();
		// Perform the ajax request - the configurations
		// below can be modified to suit your needs:
		// http://docs.jquery.com/Ajax/jQuery.ajax#options
		$.ajax(
      {
		  type: "POST",
		  url: '/fb-invite/exclud_id',
		  data: {
			'from_js' : true,
			'example_token' : Drupal.settings.exampleToken
		  },
		  dataType: "json",
		  success: function (data)
        {
        excludeId='';
        if (typeof data!= 'undefined' &&     data.length >0) {
          for(var i=0;i<data.length;i++)
            {
            if(      excludeId!='')
                  excludeId+=',';
                  excludeId+=data[0];
            }
          }
      //Construit la fenêtre de dialogue.
      FB.init({
        appId  : Drupal.settings.fb.fb_init_settings.appId
        });
      FB.ui({
        method: 'apprequests',
        message:'Invitation',
        exclude_ids :excludeId
        }, requestCallback);
      },
    error: function (xmlhttp) {
      alert('An error occured: ' + xmlhttp.status);
		  }
		});
	});
}
Petite explication :
La fonction requestCallback est appelé lorsque le formulaire d'invitation se ferme, donc quand l'utilisateur a envoyé son invitation  ou cliquez sur annulé. L'objet $.ajax() lui se charge de récupérer les ids à exclure.

Avec ce code vous disposez maintenant de l'invitation Facebook. Cependant, on ne voit pas ici comment réaliser des traitements lorsque quelqu'un accepte.
Si vous avez choisis la solution Heroku pour l'hébergement de votre application, vous n'avez qu’à modifier cette dernière pour réaliser le traitement que vous désirez notamment la suppression de votre request dans l'api de Facebook :
<?php
  //Assuming the user has already authenticated the app
   $fbu = $facebook->getUser();
  if(isset($_REQUEST['request_ids'])){
    //get the request ids from the query parameter
    $request_ids = explode(',', $_REQUEST['request_ids']);

    //for each request_id, build the full_request_id and delete request  
    foreach ($request_ids as $request_id)
      {
      $full_request_id = $request_id . '_' . $fbu;  
  
      try {
         $delete_success = $facebook->api("/$full_request_id",'DELETE');
         if ($delete_success) {
             $content.= "Successfully deleted " . $full_request_id;}
         else {
             $content.= "Delete failed".$full_request_id;}
        }          
      catch (FacebookApiException $e) {
        $content.="error".$e;}
      }
    }
    ?>
Pour forcer la redirection vers votre site on utilisera simplement :
    <script type="text/javascript">
              top.window.location = 'htttp://monsite.com';
            </script>
Intégration aux modules FB _Friend & invite :

Afin que le module FB_friend sache que l'on a envoyé une requête à facebook, on a modifier un peut son code :
Ligne 57 de fb_friend.module :
-  if (isset($_POST['ids']) && count($_POST['ids'])) {
-    $params['ids'] =$_POST['ids'];
-    $redirect = fb_invoke(FB_FRIEND_OP_REQUEST_SUBMIT, $params, NULL, 'fb_friend');
-    }

// Notify third parties
+  $redirect = fb_invoke(FB_FRIEND_OP_REQUEST_SUBMIT, $params, NULL, 'fb_friend');
+  if (isset($_POST['ids']) && count($_POST['ids'])) {
+    $params['ids'] =$_POST['ids'];
+  }
+  //Emerya changement pour la request 2.0
+  elseif(isset($_GET['ids']) && count($_GET['ids'])) {
+      $params['ids'] = unserialize( $_GET['ids']);
+   }
      else{
    // User pressed skip instead of inviting.
   $redirect = fb_invoke(FB_FRIEND_OP_REQUEST_SKIP, $params, NULL, 'fb_friend');
  }
Pour la petite explication, étant donné qu'avant l'invitation se faisait via un formulaire, les données était reçu via le $_POST, pour le moment nous avons choisis de renvoyer des données dans via le GET en les sérialisant (cf le JavaScript). N'hésitez pas à laisser un commentaire si vous voyer une meilleure méthode.

La deuxième implémentation qui peut être sympa à réaliser est avec le module invite. Pour cela, le module FB friend offre un hook, fb_friend.
/**
 * Implements hook_fb_friend().
 *Fait une entrée dans le module invite
*/
function module_facebook_fb_friend($op, $data, &$return)
  {
  // dsm($data);
  // dsm($op);
  if ($data['module'] != 'fb_friend_invite_app') {
    return;
  }
  global $_fb, $_fb_app;
  if ($data['delta'] == 'fb_friend_invite_app') 
    {
    if ($op ==  'fb_friend_request_submit') 
      {
      $infoFbu=array();
      foreach($data['ids'] as $fbuid)
        {
        // pp_facebook_getUser($fbuid)
        $infoFbu= $_fb->api($fbuid, 'GET');
        if(	 isset($infoFbu['email']) &&  !empty($infoFbu['email']))
          $mail=$infoFbu['email'];
        elseif(	 isset($infoFbu['username']) &&  !empty($infoFbu['username']))
          $mail=$infoFbu['username'].t(' via facebook');
        else
          $mail=$infoFbu['name'].t(' via facebook');
				// exit;
				$code = invite_generate_code();
				$invite = _invite_substitutions(array(
				  'email' => $mail,
				  'code'  => $code,
				  'resent'  => 0,
				  'data'  => array( 'fbu' =>$infoFbu['id']),
				));
			invite_save($invite);
        }	
    drupal_set_message(t('Votre invitation a bien été envoyée'));
		}
	} 
}
Ceci aura pour effet d'ajouter des invitations en attentes. Pour réaliser l'acceptation de l'invitation on s'est branché sur le hook_user :
<?php
/*
Implementation of Hook_user
ajoute des points aux parrains si quelqu'uns s'inscrit et qu'il a était invité via Facebook
$account : celui qui s'est inscrit

*/
function module_facebook_user($op, &$edit, &$account, $category = NULL) 
  {
  switch ($op){
  case 'login': 
// dsm($account);
    if($account->access==0 && $account->status==1)
      {
      $info= pp_facebook_getUser();

      if( isset($info['fbuser']) && $info['fbuser']['id']!='')
        {
        $res=getInfoActorFriendFacebook($account->uid);
               // var_dump($res);var_dump($account->uid);
   
        if($res!==false && $res['status']>0)
          {
          $params = array (
                    'uid' => $res['uid'],
                    'points' => 1,
                    'tid' =>27,
                   'reference'=> t("ParainID".$res['uid']),
                   'description' => t('Demande de parrainage acceptée'),
                  );
          userpoints_userpointsapi($params); 
          $userActor=user_load( $res['uid']);
          if($userActor)
            {
            $subject=' !name a rejoint le site via FACEBOOK'; 
            $body.='Youhou!';
            $body=t($body  , array('!name' => $account->name));
            $subject=t($subject  , array('!name' => $account->name));
            $message = array(
                          'to' => $userActor->mail,
                          'subject' =>$subject,
                          'body' =>    $body,
                              // 'attachments' => $attachments,
                            );
            $ok=drupal_mail_send($message);
            if(!$ok)
              drupal_set_message(t('Unable to send e-mail. Please contact the site administrator if the problem persists.'), 'error');
            $dataFbu=serialize ( array( 'fbu' => $info['fbuser']['id']));

            $code = db_result(db_query("SELECT reg_code FROM {invite} WHERE data='%s' AND uid=%d", $dataFbu,$res['uid'] ));
            db_query("UPDATE  {invite} SET email='%s' WHERE data='%s' AND uid=%d",$account->mail, $dataFbu,$res['uid'] );
            if ($code)
              {
              $invite = invite_load($code);
              if ($invite) 
                $roles = invite_process($invite, $account);
              if ($roles) 
                {
                if (!isset($edit['roles']) || !is_array($edit['roles'])) {
                  $edit['roles'] = array();
                }
                $edit['roles'] += $roles;

                // We need to notify other modules of the role change, otherwise they
                // will be unaware of it.
                user_module_invoke('update', $edit, $account);
                }
                }
              }
            }
          }
        }
      break;
    }
}

4.5
Average: 4.5 (4 votes)
Votre vote: Aucun(e)

Ajouter un commentaire

Texte simple

  • Aucune balise HTML autorisée.
  • Les adresses de pages web et de courriels sont transformées en liens automatiquement.
  • Les lignes et les paragraphes vont à la ligne automatiquement.
CAPTCHA
Image CAPTCHA