FacebookSubscriber

Public

FacebookSubscriber implements EventSubscriberInterface, writing data to user profile fields gained with Graph API

Get raw version
php
  1. <?php namespace Drupal\my_user\EventSubscriber;
  2.  
  3. // This is the interface that we are implementing.
  4. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  5. // This is a generic event class that Simple FB Connect will dispatch.
  6. use Symfony\Component\EventDispatcher\GenericEvent;
  7. // We need these classes to interact with SimpleFbConnect and FB SDK.
  8. use Drupal\simple_fb_connect\SimpleFbConnectFbFactory;
  9. use Facebook\Exceptions\FacebookSDKException;
  10. use Facebook\Exceptions\FacebookResponseException;
  11.  
  12. /**
  13.  * Event subscriptions for events dispatched by SimpleFbConnect.
  14.  */
  15. class FacebookSubscriber implements EventSubscriberInterface {
  16.  
  17. protected $facebook;
  18. protected $persistentDataHandler;
  19.  
  20. /**
  21.   * Constructor.
  22.   *
  23.   * We use dependency injection get SimpleFbConnectFbFactory.
  24.   *
  25.   * @param SimpleFbConnectFbFactory $fb_factory
  26.   * For getting Facebook and SimpleFbConnectPersistentDataHandler services.
  27.   */
  28. public function __construct(SimpleFbConnectFbFactory $fb_factory) {
  29. $this->facebook = $fb_factory->getFbService();
  30. $this->persistentDataHandler = $fb_factory->getPersistentDataHandler();
  31. }
  32.  
  33. /**
  34.   * Returns an array of event names this subscriber wants to listen to.
  35.   *
  36.   * @return array
  37.   * The event names to listen to
  38.   */
  39. static function getSubscribedEvents() {
  40. $events = [];
  41. $events['simple_fb_connect.scope'][] = ['modifyPermissionScope'];
  42. $events['simple_fb_connect.user_created'][] = ['userCreated'];
  43. $events['simple_fb_connect.user_login'][] = ['userLogin'];
  44.  
  45. return $events;
  46. }
  47.  
  48. /**
  49.   * Adds Facebook permissions to the scope array.
  50.   *
  51.   * Facebook permissions can be found at
  52.   * https://developers.facebook.com/docs/facebook-login/permissions
  53.   *
  54.   * Note that most permissions require that Facebook will review your app
  55.   * so only add those permissions that you really need. In this example we
  56.   * add 'public_profile' which you don't have to do since this permission
  57.   * is always granted.
  58.   */
  59. public function modifyPermissionScope(GenericEvent $event) {
  60. $scope = $event->getArgument('scope');
  61. $scope[] = 'public_profile,email,user_birthday,user_location,user_about_me,user_website,user_work_history';
  62. $event->setArgument('scope', $scope);
  63. }
  64.  
  65. /**
  66.   * Reacts to the event when new user is created via Simple FB Connect.
  67.   */
  68. public function userCreated(GenericEvent $event) {
  69. $user = $event->getArgument('account');
  70.  
  71. // Use the Facebook access token to make API calls.
  72. // SimpleFbConnect has stored to session for other modules.
  73. // Debug the user access token with
  74. // https://developers.facebook.com/tools/debug.
  75. $access_token = $this->persistentDataHandler->get('access_token');
  76.  
  77. // See https://developers.facebook.com/docs/facebook-login/access-tokens.
  78. if ($access_token) {
  79. try {
  80. $facebook_response = $this->facebook->get('/me?fields=id,email,name,first_name,last_name,link,gender,birthday,location,bio,picture,website,work', $access_token);
  81. if ($facebook_response->isError() === TRUE) {
  82. // Returns early if facebook responds with an error.
  83. // @todo: Add watchdog entry when facebook responds with an error.
  84. $message = t('Facebook response error!');
  85. drupal_set_message($message);
  86. \Drupal::logger('my_user')->notice($message);
  87. return;
  88. }
  89. $graph_node = $facebook_response->getGraphNode();
  90.  
  91. // The profile picture is saved with the user Facebook id to save it
  92. // as a unique public file name.
  93. $fb_id = '';
  94. $fb_id_graphnode = $graph_node->getField('id');
  95. if (!empty($fb_id_graphnode)) {
  96. $fb_id = $fb_id_graphnode;
  97.  
  98. // Get the facebook picture remote URL.
  99. $picture_url = '';
  100. $picture_url_graphnode = $graph_node->getField('picture');
  101. if (!empty($picture_url_graphnode)) {
  102. // If the picture exists then the URL will too.
  103. $picture_url = $picture_url_graphnode->getField('url');
  104. // Create file object from remote URL.
  105. $picture_img = file_get_contents($picture_url);
  106. // Save the unique file name with Facebook id.
  107. $profile_picture = file_save_data($picture_img, 'public://fb_profile_' . $fb_id . '.png', FILE_EXISTS_REPLACE);
  108. }
  109. }
  110.  
  111. $first_name = '';
  112. $first_name_graphnode = $graph_node->getField('first_name');
  113. if (!empty($first_name_graphnode)) {
  114. $first_name = $first_name_graphnode;
  115. }
  116.  
  117. $last_name = '';
  118. $last_name_graphnode = $graph_node->getField('last_name');
  119. if (!empty($last_name_graphnode)) {
  120. $last_name = $last_name_graphnode;
  121. }
  122.  
  123. // Facebook profile url.
  124. $link = '';
  125. $link_graphnode = $graph_node->getField('link');
  126. if (!empty($link_graphnode)) {
  127. $link = $link_graphnode;
  128. }
  129.  
  130. $gender = '';
  131. $gender_graphnode = $graph_node->getField('gender');
  132. if (!empty($gender_graphnode)) {
  133. $gender = $gender_graphnode;
  134. }
  135.  
  136. // Format the birthday supplied to match date format on field.
  137. $birthday = '';
  138. $birthday_graphnode = $graph_node->getField('birthday');
  139. if (!empty($birthday_graphnode)) {
  140. $birthday = $birthday_graphnode->format('Y-m-d');
  141. }
  142.  
  143. // Traverse to the user location name, the current city, state.
  144. $location = '';
  145. $location_graphnode = $graph_node->getField('location');
  146. if (!empty($location_graphnode)) {
  147. $location_name = $location_graphnode->getField('name');
  148. if (!empty($location_name)) {
  149. $location = $location_name;
  150. }
  151. }
  152.  
  153. // See
  154. // https://developers.facebook.com/docs/graph-api/reference/v2.8/user.
  155. // Get the about field, which is called bio before API v.2.8.
  156. // @todo: Verify which about_me field to get via Facebook API.
  157. $about = '';
  158. $about_graphnode = $graph_node->getField('bio');
  159. if (!empty($about_graphnode)) {
  160. $about = $about_graphnode;
  161. }
  162.  
  163. // The website field provides a dump of urls with line breaks
  164. // if more than one url exists.
  165. $website = '';
  166. $website_graphnode = $graph_node->getField('website');
  167. if (!empty($website_graphnode)) {
  168. $website = strtok($website_graphnode, "\n");
  169. }
  170.  
  171. // Traverse into the first position / job title.
  172. $job_title = '';
  173. $work_graphnode = $graph_node->getField('work');
  174. if (!empty($work_graphnode)) {
  175. $work_graphnode_first = $work_graphnode->getField('0');
  176. if (!empty($work_graphnode_first)) {
  177. $position = $work_graphnode_first->getField('position');
  178. if (!empty($position)) {
  179. $location_name = $position->getField('name');
  180. if (!empty($location_name)) {
  181. $job_title = $location_name;
  182. }
  183. }
  184. }
  185. }
  186.  
  187. // Now set user data to the extended profile fields if it exists.
  188. $user->set("field_first_name", !empty($first_name) ? $first_name : '');
  189. $user->set("field_last_name", !empty($last_name) ? $last_name : '');
  190. $user->set("field_facebook_link", !empty($link) ? $link : '');
  191. $user->set("field_gender", !empty($gender) ? $gender : '');
  192. $user->set("field_dob", !empty($birthday) ? $birthday : '');
  193. $user->set("field_location", !empty($location) ? $location : '');
  194. $user->set("field_description", !empty($about) ? $about : '');
  195. $user->set("field_profile_picture", !empty($profile_picture) ? $profile_picture : '');
  196. $user->set("field_website_link", !empty($website) ? $website : '');
  197. $user->set("field_job_title", !empty($job_title) ? $job_title : '');
  198.  
  199. // Save the user profile data.
  200. $user->save();
  201.  
  202. } catch (FacebookRequestException $ex) {
  203. // @todo: Add exception handling here for FacebookRequestExceptions.
  204.  
  205. } catch (FacebookSDKException $ex) {
  206. // @todo: Add exception handling here for all other Facebook exceptions.
  207.  
  208. }
  209. }
  210. else {
  211. $message = t('No Facebook access token found for the current user!');
  212. drupal_set_message($message);
  213. \Drupal::logger('my_user')->notice($message);
  214. }
  215.  
  216. }
  217.  
  218. /**
  219.   * Reacts to the event when user logs in via Simple FB Connect.
  220.   *
  221.   * This example adds role 'facebook' to the user if the user
  222.   * didn't have that role already. You have to create the role manually.
  223.   *
  224.   * This function also demonstrates how you can get the access token for the
  225.   * current user and how to make your own API calls using Facebook service.
  226.   */
  227. public function userLogin(GenericEvent $event) {
  228. // $user = $event->getArgument('account');
  229.  
  230. // drupal_set_message("Debug: user logged in. This message is from userLogin!");
  231.  
  232. }
  233.  
  234. }