You are here

facebook_pull.module in Facebook Pull 7.3

Same filename and directory in other branches
  1. 6 facebook_pull.module
  2. 7 facebook_pull.module
  3. 7.2 facebook_pull.module

Facebook Pull Module for getting content from Facebook graph.

File

facebook_pull.module
View source
<?php

/**
 * @file
 * Facebook Pull Module for getting content from Facebook graph.
 */
define('FACEBOOK_PULL_CACHETIME', 1200);

/**
 * Implements hook_init().
 */
function facebook_pull_init() {
  drupal_add_css(drupal_get_path('module', 'facebook_pull') . '/facebook_pull.css');
}

/**
 * Implements hook_theme().
 */
function facebook_pull_theme($existing, $type, $theme, $path) {
  $theme = array(
    'facebook_pull_feed' => array(
      'variables' => array(
        'items' => array(),
      ),
      'template' => 'facebook_pull-feed',
    ),
    'facebook_pull_notes' => array(
      'variables' => array(
        'feedid' => 0,
        'items' => array(),
      ),
      'template' => 'facebook_pull-notes',
    ),
  );
  return $theme;
}

/**
 * Implements hook_perm().
 */
function facebook_pull_permission() {
  return array(
    'administer facebook pull' => array(
      'title' => t('Administer facebook pull'),
    ),
  );
}

/**
 * Implements hook_menu().
 */
function facebook_pull_menu() {
  $items = array();
  $items['admin/config/services/facebook-pull'] = array(
    'title' => 'Facebook pull',
    'description' => 'Set Facebook API details for facebook blocks.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'facebook_pull_settings',
    ),
    'access arguments' => array(
      'administer facebook pull',
    ),
    'type' => MENU_NORMAL_ITEM,
  );
  return $items;
}

/**
 * Implements hook_block_list().
 */
function facebook_pull_block_info() {
  $blocks = array();
  $blocks['facebook_pull_default'] = array(
    'info' => t('Facebook stream'),
    'weight' => 0,
    'status' => 0,
    'cache' => DRUPAL_CACHE_GLOBAL,
  );
  return $blocks;
}

/**
 * Implements hook_block_view().
 */
function facebook_pull_block_view($delta = '') {
  $block = array();
  switch ($delta) {
    case 'facebook_pull_default':
      $block = array(
        'subject' => t('Facebook stream'),
        'content' => _facebook_pull_render_block(),
      );
      break;
  }
  return $block;
}

/**
 * Implements hook_ctools_plugin_api().
 */
function facebook_pull_ctools_plugin_api($module, $api) {
  return array(
    'version' => 1,
  );
}

/**
 * Implements hook_boxes_plugins().
 */
function facebook_pull_boxes_plugins() {
  $info = array();
  $path = drupal_get_path('module', 'facebook_pull') . '/plugins';
  $info['facebook_pull'] = array(
    'title' => 'Facebook box',
    'handler' => array(
      'parent' => 'box',
      'class' => 'facebook_pull_box',
      'file' => 'facebook_pull_box.inc',
      'path' => $path,
    ),
  );
  return $info;
}

/**
 * Form: Administration page settings.
 */
function facebook_pull_settings($form_state) {
  $form = array();
  $application_id = l(t('Application ID'), 'https://developers.facebook.com/apps');
  $form['facebook_pull_app_id'] = array(
    '#type' => 'textfield',
    '#title' => t('App ID'),
    '#default_value' => t(variable_get('facebook_pull_app_id', '')),
    '#description' => t('Unique !application_id for your facebook app.', array(
      '!application_id' => $application_id,
    )),
  );
  $form['facebook_pull_app_secret'] = array(
    '#type' => 'textfield',
    '#title' => t('App Secret'),
    '#default_value' => t(variable_get('facebook_pull_app_secret', '')),
    '#description' => t('Your sites app secret.'),
  );
  $graph_link = l(t('Graph ID'), 'http://developers.facebook.com/docs/reference/api/');
  $form['facebook_pull_graph_id'] = array(
    '#type' => 'textfield',
    '#title' => t('Graph ID'),
    '#default_value' => t(variable_get('facebook_pull_graph_id', '')),
    '#description' => t('The !graph_id of the page, user, or group.', array(
      '!graph_id' => $graph_link,
    )),
  );
  $form['facebook_pull_object_type'] = array(
    '#type' => 'textfield',
    '#title' => t('Object type'),
    '#default_value' => t(variable_get('facebook_pull_object_type', '')),
    '#description' => t('The object type to pull. This is most likely going to be "feed". Facebook API documentation may offer other endpoints such as "posts" or "tagged". They are not thoroughly tested.'),
  );
  $form['facebook_pull_limit'] = array(
    '#type' => 'textfield',
    '#title' => t('Limit'),
    '#size' => 5,
    '#default_value' => t(variable_get('facebook_pull_limit', '')),
    '#description' => t('How many posts to show in the box by default. If you have not entered a default limit here then it will default to 10.'),
  );
  $form['facebook_pull_fields'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Fields to retrieve from Facebook'),
    '#options' => _facebook_pull_default_options(),
    '#default_value' => variable_get('facebook_pull_fields', array_keys(_facebook_pull_default_options())),
  );
  return system_settings_form($form);
}

/**
 * Serve up a facebook feed from the cache.
 */
function facebook_pull_render($graph_id, $type, $app_id, $app_secret, $options = array()) {
  $data = _facebook_pull_feed_cached($graph_id, $type, $app_id, $app_secret, $options);
  if (!$data) {
    return '';
  }
  return theme('facebook_pull_feed', array(
    'items' => $data,
  ));
}

/**
 * Serve up facebook notes.
 */
function facebook_pull_notes($id, $key, $viewer = 0, $limit = 5) {
  $data = _facebook_pull_notes_cached($id, $key, $viewer);
  if (!$data) {
    return '';
  }
  $feed = simplexml_load_string($data);
  $entries = array();
  for ($i = 0; $i < $limit; $i++) {
    $entries[] = $feed->entry[$i];
  }
  return theme('facebook_pull_notes', array(
    'feedid' => $id,
    'items' => $entries,
  ));
}

/**
 * Pull the notes but check the cache first.
 */
function _facebook_pull_notes_cached($id, $key, $viewer = 0) {
  $cache_key = sprintf("%s-%s-%s", $id, $key, $viewer);
  $cache = cache_get($cache_key);
  if (!$cache || $cache->created + FACEBOOK_PULL_CACHETIME < REQUEST_TIME) {
    $data = _facebook_pull_notes($id, $key, $viewer);
    cache_set($cache_key, $data, 'cache', CACHE_TEMPORARY);
  }
  else {
    $data = $cache->data;
  }
  return $data;
}

/**
 * We need a specific way to access notes.
 *
 * Notes are currently not available
 * due to the following bug in the facebook graph.
 *
 * Http://bugs.developers.facebook.net/show_bug.cgi?id=18266
 */
function _facebook_pull_notes($id, $key, $viewer = 0) {
  $data = array(
    'id' => $id,
    'viewer' => $viewer,
    'key' => $key,
    'format' => 'atom10',
  );
  $qs = http_build_query($data, '', '&');
  $url = 'http://www.facebook.com/feeds/notes.php?' . $qs;
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_HEADER, 0);
  curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
  curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0');
  ob_start();
  curl_exec($ch);
  $raw = ob_get_contents();
  ob_end_clean();

  // HBD.
  curl_close($ch);
  return $raw;
}

/**
 * Pull data from a facebook feed and cache it.
 */
function _facebook_pull_feed_cached($graph_id, $type, $app_id, $app_secret, $options = array()) {
  $cache_key = sprintf("%s-%s-%s", $graph_id, $type, http_build_query($options, '', '-'));
  $cache = cache_get($cache_key);
  if (!$cache || $cache->created + FACEBOOK_PULL_CACHETIME < REQUEST_TIME) {
    $token = _facebook_pull_accesstoken($app_id, $app_secret);
    $data = _facebook_pull_feed($graph_id, $type, $token, $options);
    cache_set($cache_key, $data, 'cache', CACHE_TEMPORARY);
  }
  else {
    $data = $cache->data;
  }
  return $data;
}

/**
 * Pull data from a facebook feed.
 */
function _facebook_pull_feed($graph_id, $type, $token, $options = array()) {
  $qs = http_build_query($options, '', '&');
  $url = "https://graph.facebook.com/%s/%s?%s&%s";
  $full_url = sprintf($url, $graph_id, $type, $token, $qs);
  $raw = drupal_http_request($full_url);
  $raw = $raw->data;
  $data = json_decode($raw);
  if (!isset($data->data)) {
    $message = 'Failed to fetch data from the Facebook Graph';
    $variables = array();
    watchdog('facebook_pull', $message, $variables, WATCHDOG_WARNING);
    return FALSE;
  }
  return $data->data;
}

/**
 * Get an access token.
 */
function _facebook_pull_accesstoken($app_id, $app_secret) {
  $endpoint = 'https://graph.facebook.com/oauth/access_token?client_id=%s&client_secret=%s&grant_type=client_credentials';
  $full_url = sprintf($endpoint, $app_id, $app_secret);
  $token = drupal_http_request($full_url);
  $token = $token->data;
  if (!$token) {
    $message = 'Failed to fetch data from the Facebook Graph';
    $variables = array();
    watchdog('facebook_pull', $message, $variables, WATCHDOG_WARNING);
    return FALSE;
  }
  $token = json_decode($token, TRUE);
  if (json_last_error() !== JSON_ERROR_NONE) {
    $message = 'Facebook Graph authentication response invalid.';
    watchdog('facebook_pull', $message, array(), WATCHDOG_WARNING);
    return FALSE;
  }
  if (!isset($token['access_token'])) {
    $message = 'Facebook Graph failed to provide access token.';
    watchdog('facebook_pull', $message, array(), WATCHDOG_WARNING);
    return FALSE;
  }
  return http_build_query($token);
}

/**
 * Render a single block using the configured settings.
 */
function _facebook_pull_render_block() {
  global $language;
  $app_id = variable_get('facebook_pull_app_id', '');
  $app_secret = variable_get('facebook_pull_app_secret', '');
  $graph_id = variable_get('facebook_pull_graph_id', '');
  $type = variable_get('facebook_pull_object_type', '');
  $limit = variable_get('facebook_pull_limit', '');
  $fields = implode(',', array_filter(variable_get('facebook_pull_fields', _facebook_pull_default_options())));
  $options = array(
    'limit' => $limit,
    'locale' => $language->language,
    'fields' => $fields,
  );
  return facebook_pull_render($graph_id, $type, $app_id, $app_secret, $options);
}

// Added for Notes section
// https://www.drupal.org/node/1993764
//

/**
 * Implements hook_preprocess_HOOK().
 */
function facebook_pull_preprocess_facebook_pull_feed(&$variables) {
  if ($variables['items']) {
    global $is_https;
    foreach ($variables['items'] as &$item) {
      if (property_exists($item, 'from')) {
        $from =& $item->from;
        $scheme = $is_https ? 'https' : 'http';
        $from->picture = "{$scheme}://graph.facebook.com/{$from->id}/picture";
        if (isset($from->name)) {
          $from->name = check_plain($from->name);
        }
        if (isset($from->id)) {
          $from->id = check_plain($from->id);
        }
      }
      if (isset($item->story)) {
        $item->story = check_plain($item->story);
      }
      if (isset($item->description)) {
        $item->description = check_plain($item->description);
      }
      if (isset($item->question)) {
        $item->question = check_plain($item->question);
      }
      if (isset($item->message)) {
        $item->message = check_plain($item->message);
      }
      if (isset($item->picture)) {
        $item->picture = check_url($item->picture);
      }
    }
  }
}

/**
 * Implements hook_preprocess_HOOK().
 */
function facebook_pull_preprocess_facebook_pull_notes(&$variables) {
  if ($variables['feedid']) {
    global $is_https;
    $scheme = $is_https ? 'https' : 'http';
    $variables['picture'] = "{$scheme}://graph.facebook.com/{$variables['feedid']}/picture";
    $variables['feedid'] = check_plain($variables['feedid']);
  }
  if ($variables['items']) {
    foreach ($variables['items'] as &$item) {
      if (isset($item->link['href'])) {
        $item->link['href'] = check_url($item->link['href']);
      }
      if (isset($item->summary)) {
        $item->summary = check_plain($item->summary);
      }
      if (isset($item->published)) {
        $item->published = check_plain($item->published);
      }
      if (isset($item->title)) {
        $item->title = check_plain($item->title);
      }
    }
  }
}

/**
 * Helper function to return default api options array.
 */
function _facebook_pull_default_options() {
  return array(
    'picture' => 'picture',
    'message' => 'message',
    'from' => 'from',
    'type' => 'type',
    'created_time' => 'created_time',
    'link' => 'link',
    'description' => 'description',
    'name' => 'name',
  );
}

Functions

Namesort descending Description
facebook_pull_block_info Implements hook_block_list().
facebook_pull_block_view Implements hook_block_view().
facebook_pull_boxes_plugins Implements hook_boxes_plugins().
facebook_pull_ctools_plugin_api Implements hook_ctools_plugin_api().
facebook_pull_init Implements hook_init().
facebook_pull_menu Implements hook_menu().
facebook_pull_notes Serve up facebook notes.
facebook_pull_permission Implements hook_perm().
facebook_pull_preprocess_facebook_pull_feed Implements hook_preprocess_HOOK().
facebook_pull_preprocess_facebook_pull_notes Implements hook_preprocess_HOOK().
facebook_pull_render Serve up a facebook feed from the cache.
facebook_pull_settings Form: Administration page settings.
facebook_pull_theme Implements hook_theme().
_facebook_pull_accesstoken Get an access token.
_facebook_pull_default_options Helper function to return default api options array.
_facebook_pull_feed Pull data from a facebook feed.
_facebook_pull_feed_cached Pull data from a facebook feed and cache it.
_facebook_pull_notes We need a specific way to access notes.
_facebook_pull_notes_cached Pull the notes but check the cache first.
_facebook_pull_render_block Render a single block using the configured settings.

Constants

Namesort descending Description
FACEBOOK_PULL_CACHETIME @file Facebook Pull Module for getting content from Facebook graph.