Simple FB connect Drupal 8 Mapping custom fields from Facebook

Simple FB Connect Drupal module  allows users to register and login to your Drupal site with their Facebook account.

Indeed, as the modules name suggests, its one of the easiest ways how to connect Facebook to Drupal. And as I had already worked with this module a few years ago (see: Drupal Simple FB connect + User Form Theming ) now, when working on idea about possible Drupal Dating portal,  I decided to implement Simple FB Connect. In this article I'll write down my notes on how to map custom Facebook fields to Drupal 8 using this module.

I should note that I was working on Drupal 8.4.2 minimal profile installed. 

Before proceeding to the technical part, make sure you have created:

For the sake of ease for this tutorial I will cover details on how to map fields from Facebook's person's public profile only (for enabling additional fields you will need to make Facebook review for your app)

The following properties on the user object are enabled by default: (See: Permissions Reference - Facebook Login)

  • id
  • cover
  • name
  • first_name
  • last_name
  • age_range
  • link
  • gender
  • locale
  • picture
  • timezone
  • updated_time
  • verified

Now, once we are all set up, let's do two things:

  • Create fields for Drupal user profiles
  • Creating a custom module for mapping Facebook fields to Drupal fields using Simple FB connect.

Adding custom fields for Drupal user profiles

For this example I created following fields:

  • First name field_first_name Text (plain)
  • Last name field_last_name Text (plain)
  • Gender field_gender Text (plain)
  • Age Range field_age_range Text (plain)
  • Locale field_locale Text (plain)

Your setup might differ, but hopefully you got the picture.

Custom module for mapping FB fields

A great reading and tutorial is already provided on modules page, see: EventSubscriber example. Here I will just reproduce what's already written and some minor changes for mapping fields from Facebook.

mymodule/mymodule.info.yml

name: My Module
description: 'Example module demonstrating interaction with Simple FB Connect.'
package: Custom
type: module
core: 8.x
dependencies:
  - simple_fb_connect

mymodule/mymodule.services.yml

services:
  mymodule.subscriber:
    class: Drupal\mymodule\EventSubscriber\MyModuleSubscriber
    arguments:
      - @simple_fb_connect.fb_factory
    tags:
      - {name: event_subscriber}

Pay attention when copy-pasting the content of the services file. The intendation must be exactly like it is here (indent does NOT use tabulators but two space bars). If you get a white screen of death (PHP fatal error), please fix the indents, clear Drupal caches and try again.

mymodule/src/EventSubscriber/MyModuleSubscriber.php

A slightingly modified file already, please see EventSubscriber example for original. Inspired by themes mania

facebook = $fb_factory->getFbService();
    $this->persistentDataHandler = $fb_factory->getPersistentDataHandler();
  }

  /**
   * Returns an array of event names this subscriber wants to listen to.
   *
   * @return array
   *   The event names to listen to
   */
  static function getSubscribedEvents() {
    $events = array();
    $events['simple_fb_connect.scope'][] = array('modifyPermissionScope');
    $events['simple_fb_connect.user_created'][] = array('userCreated');
    $events['simple_fb_connect.user_login'][] = array('userLogin');
    return $events;
  }

  /**
   * Adds Facebook permissions to the scope array.
   *
   * Facebook permissions can be found at
   * https://developers.facebook.com/docs/facebook-login/permissions
   *
   * Note that most permissions require that Facebook will review your app
   * so only add those permissions that you really need. In this example we
   * add 'public_profile' which you don't have to do since this permission
   * is always granted.
   */
  public function modifyPermissionScope(GenericEvent $event) {
    $scope = $event->getArgument('scope');
    // Add the permission here. In this example we add 'public_profile'.
    $scope[] = 'public_profile';
    $event->setArgument('scope', $scope);
  }

  /**
   * Reacts to the event when new user is created via Simple FB Connect.
   *
   */
  public function userCreated(GenericEvent $event) {
    $user = $event->getArgument('account');

    // Enter your own code here. Remember to save the user with $user->save()
    // if you modify the user object.
    drupal_set_message("Debug: user created. This message is from mymodule!");
  }
  /**
   * Reacts to the event when user logs in via Simple FB Connect.
   *
   * This example adds role 'facebook' to the user if the user
   * didn't have that role already. You have to create the role manually.
   *
   * This function also demonstrates how you can get the access token for the
   * current user and how to make your own API calls using Facebook service.
   */
  public function userLogin(GenericEvent $event) {
    $user = $event->getArgument('account');

    // Enter your code here. Remember to save the user with $user->save()
    // if you modify the user object.
    drupal_set_message("Debug: user logged in. This message is from mymodule!");

    // Let's add a role 'facebook' for the user if she didn't have it already.
    // The role itself must obviously be first created manually.
	
    $user->addRole('facebook');
    $user->save();


    // Let's see how we can get make our own API calls to Facebook. We need
    // user's Facebook access token, which SimpleFbConnect has stored to session
    // for other modules.
    $access_token = $this->persistentDataHandler->get('access_token');
    if ($access_token) {
      try {
       $graph_node = $this->facebook->get('/me?fields=name,first_name,last_name,gender,age_range,locale', $access_token)->getGraphNode();
        $name = $graph_node->getField('name');
        $first_name = $graph_node->getField('first_name');
        $last_name = $graph_node->getField('last_name');
        $gender = $graph_node->getField('gender');
        $age_range = $graph_node->getField('age_range');
        $locale = $graph_node->getField('locale');
        drupal_set_message("We were able to retreive following data from Facebook: " . $name . $first_name . $last_name . $gender . $age_range . $locale );
		$user->set("field_first_name", $first_name);
		$user->set("field_last_name", $last_name);
		$user->set("field_gender", $gender);
		$user->set("field_age_range", $age_range);
		$user->set("field_locale", $locale);
	    $user->save();
      }

      catch (FacebookRequestException $ex) {
        // Add exception handling here for FacebookRequestExceptions.
      }
      catch (FacebookSDKException $ex) {
        // Add exception handling here for all other exceptions.
      }
    }
    else {
      drupal_set_message("No FB access token found for current user!");
    }
  }

}

Now once configured and enabled, after login with Facebook connect, here is the result and data I was able to store in Drupal:

Mapping Facebook user fields to Drupal user fields

Mapping Facebook user fields to Drupal user fields

Hope it helps, and as usual if you have any questions or comments - please share bellow in the comments section.