You are here

fb_social.module in Facebook social plugins integration 7.2

Same filename and directory in other branches
  1. 6.2 fb_social.module
  2. 6 fb_social.module

File

fb_social.module
View source
<?php

// facebook developers site
define('FB_REF_BASE_URL', 'http://developers.facebook.com/docs/reference/plugins/');

/**
 * Implements hook_rdf_namespaces().
 */
function fb_social_rdf_namespaces() {
  return array(
    'og' => 'http://ogp.me/ns#',
    'fb' => 'http://www.facebook.com/2008/fbml',
  );
}

/**
 * Implements hook_menu().
 */
function fb_social_menu() {
  $items = array();
  $items['fb_social/channel'] = array(
    'type' => MENU_CALLBACK,
    'description' => 'Facebook Custom Channel URL',
    'page callback' => 'fb_social_custom_channel_url',
    'access callback' => TRUE,
  );
  $items['admin/structure/fbsocial'] = array(
    'title' => 'Facebook social',
    'description' => 'Settings for facebook social plugins.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'fb_social_admin_settings_form',
    ),
    'file' => 'fb_social.admin.inc',
    'access callback' => 'user_access',
    'access arguments' => array(
      'administer site configuration',
    ),
  );
  $items['admin/structure/fbsocial/settings'] = array(
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'title' => 'Settings',
    'description' => 'Settings for facebook social plugins.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'fb_social_admin_settings_form',
    ),
    'file' => 'fb_social.admin.inc',
    'access callback' => 'user_access',
    'access arguments' => array(
      'administer site configuration',
    ),
  );
  return $items;
}

/**
 * Implements hook_block_info().
 */
function fb_social_block_info() {
  $blocks = array();

  // load all presets
  if ($presets = fb_social_get_presets()) {
    foreach ($presets as $preset) {
      if ($preset->settings['block']) {
        $blocks[$preset->name] = array(
          'info' => $preset->name . ' block',
          'cache' => DRUPAL_NO_CACHE,
        );
      }
    }
  }
  return $blocks;
}

/**
 * Implements hook_block_view().
 */
function fb_social_block_view($delta) {
  if ($preset = fb_social_get_presets($name = $delta)) {
    $block['subject'] = t('');
    $block['content'] = fb_social_preset_view($preset);
    return $block;
  }
}

/**
 * Implementation of hook_theme
 */
function fb_social_theme($existing, $type, $theme, $path) {
  $path1 = drupal_get_path('module', 'fb_social');
  return array(
    'fb_social_plugin' => array(
      'template' => 'fb-social-plugin',
      'path' => "{$path1}/theme",
      'variables' => array(
        'plugin_type' => NULL,
        'options' => array(),
      ),
    ),
  );
}

/**
 * Implements preprocess_hook
 */
function fb_social_preprocess_fb_social_plugin(&$variables) {
  global $_fb_script_init;
  $_fb_script_init = TRUE;
  $plugin = fb_social_fb_plugin_load($variables['plugin_type']);

  // delegate to plugin's preprocess function
  $function = ctools_plugin_get_function($plugin, 'hook_preprocess_fb_social_plugin');
  if ($function) {
    $function($variables);
  }

  // are we rendering html5 or xfbml
  $markup_type = variable_get('fb_social_markup_type', 'xfbml');
  $variables['tag_name'] = $markup_type == "xfbml" ? "fb:" . $plugin['html tag name'] : "div";
  if ($markup_type == 'html5') {
    foreach ($variables['options'] as $key => $value) {
      $variables['options']["data-" . $key] = $value;
      unset($variables['options'][$key]);
    }
    $variables['options'] = array(
      'class' => "fb-" . $plugin['html tag name'],
    ) + $variables['options'];
  }
}

/**
 * Implements hook_node_view().
 */
function fb_social_node_view($node, $view_mode = 'full') {
  $links = fb_social_link('node', $node, $view_mode);
  $node->content['links']['fb_social'] = array(
    '#theme' => 'links__node__fb_social',
    '#links' => $links,
    '#attributes' => array(
      'class' => array(
        'links',
        'inline',
      ),
    ),
  );
  if ($presets = fb_social_get_presets()) {
    foreach ($presets as $preset) {
      $plugin = fb_social_fb_plugin_load($preset->plugin_type);

      // delegate hook_nodeapi_view
      $function = ctools_plugin_get_function($plugin, 'hook_nodeapi_view');
      if ($function) {
        $function($preset, $node, $view_mode);
      }
    }
  }
}

/**
 * Implements hook_content_extra_fields.
 */
function fb_social_field_extra_fields() {
  $extras = array();
  if ($presets = fb_social_get_presets()) {
    foreach ($presets as $preset) {
      $plugin = fb_social_fb_plugin_load($preset->plugin_type);
      $function = ctools_plugin_get_function($plugin, 'hook_field_extra_fields');
      if ($function) {
        $function($extras, $preset);
      }
    }
  }
  return $extras;
}

/**
 * Fake hook_link (as in D6); for easy maintanance only
 */
function fb_social_link($type, $object = NULL, $view_mode = 'full') {
  $links = array();
  if ($presets = fb_social_get_presets()) {
    foreach ($presets as $preset) {

      // let plugins say something
      $plugin = fb_social_fb_plugin_load($preset->plugin_type);
      $function = ctools_plugin_get_function($plugin, 'hook_link');
      if ($function) {
        $links += $function($preset, $type, $object, $view_mode);
      }
    }
  }
  if (isset($links)) {
    return $links;
  }
}

// ctools hooks / api

/**
 * Implements hook_ctools_plugin_type() to inform the plugin system 
 * owns 'fb_plugin' plugin types.
 *
 * "process" tells ctools that by default each 
 * plugin has some default functions named consistently 
 * after the plugin name
 * @see _fb_social_ctools_plugin_fb_plugin_process()
 */
function fb_social_ctools_plugin_type() {
  return array(
    'fb_plugin' => array(
      'process' => '_fb_social_ctools_plugin_fb_plugin_process',
    ),
  );
}

/**
 * Implementation of hook_ctools_plugin_api().
 */
function fb_social_ctools_plugin_api($module, $api) {
  if ($module == 'fb_social' && $api == 'plugins') {
    return array(
      'version' => 1,
    );
  }

  //boxes
  if ($module == 'boxes' && $api == 'plugins') {
    return array(
      'version' => 1,
    );
  }
}

/**
 * Implementation of hook_ctools_plugin_directory().
 */
function fb_social_ctools_plugin_directory($module, $type) {
  return 'plugins/' . $type;
}

/**
 * Helper function for ctools plugin 'process' 
 * @param $plugin
 * @param $info
 * @see fb_social_ctools_plugin_fb_plugin()
 */
function _fb_social_ctools_plugin_fb_plugin_process(&$plugin, $info) {
  $plugin['default values'] = $plugin['name'] . '_defaults';
  $plugin['fb plugin form'] = $plugin['name'] . '_fb_settings';
  $plugin['drupal settings form'] = $plugin['name'] . '_drupal_settings';
}

// ctools wrapper functions for 'fb_plugin"

/**
 * load a specific fb_plugin or all of them
 */
function fb_social_fb_plugin_load($type = NULL) {
  ctools_include('plugins');
  $plugins = ctools_get_plugins('fb_social', 'fb_plugin');
  if (isset($type)) {
    return $plugins[$type];
  }
  return $plugins;
}

/**
 * Return the default vaules of a certain plugin 
 * type as defined by facebook
 * @param $type the plugin type/name (i.e. like).
 */
function fb_social_fb_plugin_defaults($type) {
  $plugin = fb_social_fb_plugin_load($type);
  $function = ctools_plugin_get_function($plugin, 'default values');
  if ($function) {
    return $function();
  }
  return array();
}

/**
 * Return the facebook plugin form for a given type
 * @param $type the plugin type/name (i.e. like).
 */
function fb_social_fb_plugin_fb_settings_form($type, $options) {
  $form = array();
  $plugin = fb_social_fb_plugin_load($type);
  $url = FB_REF_BASE_URL . $plugin['html tag name'];
  $l = l("facebook documentation page", $url, array(
    'attributes' => array(
      'target' => '_blank',
    ),
  ));
  $desc = t("For more information about this plugin and its attributes please check out the !facebookdoc", array(
    '!facebookdoc' => $l,
  ));
  $form['help'] = array(
    '#value' => "<div>" . $desc . "</div>",
  );
  $function = ctools_plugin_get_function($plugin, 'fb plugin form');
  if ($function) {
    $form += $function($options);
  }
  return $form;
}

/**
 * Return the drupal settings form for a given plugin type
 * @param $type the plugin type/name (i.e. like).
 */
function fb_social_fb_plugin_drupal_settings_form($type, $options) {
  $form = array();
  $plugin = fb_social_fb_plugin_load($type);
  $function = ctools_plugin_get_function($plugin, 'drupal settings form');
  if ($function) {
    $form = $function($options);
  }
  return $form;
}

// ctools wrapper functions for "fb social preset"

/**
 * load the preset
 * @param $name
 * the preset name
 * @param $reset
 */
function fb_social_preset_load($name = NULL, $reset = FALSE) {
  ctools_include('export');
  if ($reset) {
    ctools_export_load_object_reset('fb_social_preset');
  }
  $presets = ctools_export_load_object('fb_social_preset', 'all');
  if (isset($name)) {
    return isset($presets[$name]) ? $presets[$name] : FALSE;
  }
  return $presets;
}

/**
 * Get all presets or a preset by name. By default
 * it returns only enabled presets.
 * 
 * @param $name
 *    the preset name
 * @param $enabled
 *    
 * @param $reset
 */
function fb_social_get_presets($name = NULL, $enabled = TRUE, $reset = FALSE) {
  $presets = fb_social_preset_load($name, $reset);
  if (empty($presets)) {
    return FALSE;
  }
  if (is_object($presets)) {
    $presets = array(
      $presets->name => $presets,
    );
  }
  if ($enabled) {
    $presets = array_filter($presets, '_fb_social_enabled_presets_filter');
  }
  if (isset($name)) {
    return isset($presets[$name]) ? $presets[$name] : FALSE;
  }
  return $presets;
}

/**
 * filter presets based on come conditions $args
 * @see ctools_export_load_object()
 */
function _fb_social_enabled_presets_filter($preset) {
  return isset($preset->disabled) && $preset->disabled ? FALSE : TRUE;
}
function fb_social_get_presets_by_type($type, $en = TRUE) {
  $result = array();
  $presets = fb_social_get_presets($name = NULL, $enabled = $en);
  if (!empty($presets)) {
    foreach ($presets as $preset) {
      if ($preset->plugin_type == $type) {
        $result[] = $preset;
      }
    }
  }
  return $result;
}

// boxes integration

/**
 * Implementation of hook_boxes_plugins().
 */
function fb_social_boxes_plugins() {
  $info = array();
  $path = drupal_get_path('module', 'fb_social') . '/plugins/boxes';
  $info['fb_social_default'] = array(
    'handler' => array(
      'class' => 'fb_social_default',
      'file' => 'fb_social_default.inc',
      'path' => $path,
      'parent' => 'box',
    ),
  );
  $info['fb_social_like'] = array(
    'title' => 'facebook like',
    'handler' => array(
      'class' => 'fb_social_like',
      'file' => 'fb_social_like.inc',
      'path' => $path,
      'parent' => 'fb_social_default',
    ),
  );
  $info['fb_social_likebox'] = array(
    'title' => 'facebook likebox',
    'handler' => array(
      'class' => 'fb_social_likebox',
      'file' => 'fb_social_likebox.inc',
      'path' => $path,
      'parent' => 'fb_social_default',
    ),
  );
  $info['fb_social_send'] = array(
    'title' => 'facebook send',
    'handler' => array(
      'class' => 'fb_social_send',
      'file' => 'fb_social_send.inc',
      'path' => $path,
      'parent' => 'fb_social_default',
    ),
  );
  $info['fb_social_facepile'] = array(
    'title' => 'facebook facepile',
    'handler' => array(
      'class' => 'fb_social_facepile',
      'file' => 'fb_social_facepile.inc',
      'path' => $path,
      'parent' => 'fb_social_default',
    ),
  );
  $info['fb_social_livestream'] = array(
    'title' => 'facebook livestream',
    'handler' => array(
      'class' => 'fb_social_livestream',
      'file' => 'fb_social_livestream.inc',
      'path' => $path,
      'parent' => 'fb_social_default',
    ),
  );
  $info['fb_social_comments'] = array(
    'title' => 'facebook comments',
    'handler' => array(
      'class' => 'fb_social_comments',
      'file' => 'fb_social_comments.inc',
      'path' => $path,
      'parent' => 'fb_social_default',
    ),
  );

  // Truncate the name of the plugin because the delta column in the blocks
  // table is limited to 32 characters.
  $info['fb_social_recommend'] = array(
    'title' => 'facebook recommendations',
    'handler' => array(
      'class' => 'fb_social_recommendations',
      'file' => 'fb_social_recommendations.inc',
      'path' => $path,
      'parent' => 'fb_social_default',
    ),
  );
  $info['fb_social_activityf'] = array(
    'title' => 'facebook activity feed',
    'handler' => array(
      'class' => 'fb_social_activityfeed',
      'file' => 'fb_social_activityfeed.inc',
      'path' => $path,
      'parent' => 'fb_social_default',
    ),
  );
  return $info;
}

/**
 * returns the fbml content of the plugin
 */
function fb_social_preset_view($preset) {
  $plugin_type = $preset->plugin_type;
  $options = $preset->fb_attrs;
  $output = theme('fb_social_plugin', array(
    'plugin_type' => $plugin_type,
    'options' => $options,
  ));

  // if this is a "comment" plugin, get comments from facebook and print them
  // behind the iframe
  if ($plugin_type == 'comments' && isset($preset->settings['plugin_comments_seo']) && $preset->settings['plugin_comments_seo']['seo']) {
    $cache_length = $preset->settings['plugin_comments_seo']['cache_length'];
    $nr_comments = $preset->settings['plugin_comments_seo']['nr_comments'];
    $url = empty($options['href']) ? fb_social_url($_GET['q']) : $options['href'];
    module_load_include('inc', 'fb_social', 'plugins/fb_plugin/comments');
    $output .= _fb_social_comments_seo($url, $nr_comments, $cache_length);
  }
  return $output;
}

/**
 * returns the fbml content of the plugin
 */
function fb_social_box_view($box) {
  $plugin_type = $box->fb_plugin_name;
  $options = $box->options;
  $output = theme('fb_social_plugin', array(
    'plugin_type' => $plugin_type,
    'options' => $options,
  ));
  if ($plugin_type == 'comments') {
    $cache_length = 720;
    $nr_comments = 100;
    $url = empty($options['href']) ? fb_social_url($_GET['q']) : $options['href'];
    module_load_include('inc', 'fb_social', 'plugins/fb_plugin/comments');
    $output .= _fb_social_comments_seo($url, $nr_comments, $cache_length);
  }
  return $output;
}

/**
 * Implements hook_page_alter().
 */
function fb_social_page_alter(&$page) {
  global $language, $_fb_script_init, $base_url;

  // If their is no fb plugin enabled on this page, do not load fb script then
  if (!$_fb_script_init) {
    return;
  }
  $languages = _map_active_languages();
  if (fb_social_auto_language()) {
    if (array_key_exists($language->language, $languages)) {
      $fb_locale = $languages[$language->language];
    }
    else {
      drupal_set_message(t("There is no mapping for the current language. Using the default locale."));
    }
  }
  else {
    $fb_locale = variable_get('fb_social_locale', 'en_US');
  }
  $appid = variable_get('fb_social_appid', '');
  $channel_url = $base_url . "/fb_social/channel";
  $output = '<div id="fb-root"></div>';
  $output .= "<script type=\"text/javascript\">\n     window.fbAsyncInit = function() {\n       FB.init({\n         appId: " . drupal_json_encode($appid) . ",\n         status: true,\n         cookie: true,\n         xfbml: true,\n         oauth : true,\n         channelUrl: " . drupal_json_encode($channel_url) . "\n         });\n  \n         ";

  // let each module subscribe to different events
  $output .= implode("\n", module_invoke_all('fb_social_event_subscribe'));
  $output .= "\n     };\n     (function() {\n       var e = document.createElement('script');\n       e.async = true;\n       e.src = document.location.protocol + '//connect.facebook.net/" . $fb_locale . "/all.js';\n       document.getElementById('fb-root').appendChild(e);\n     }());\n  </script>";

  // Allow the location to be changed, if necessary, but default to load at the
  // top of the page per the official Facebook JavaScript SDK documentation:
  // http://developers.facebook.com/docs/reference/javascript/
  if (variable_get('fb_social_fbroot_top', TRUE)) {
    $location = 'page_top';
  }
  else {
    $location = 'page_bottom';
  }
  $page[$location]['fb_social'] = array(
    '#markup' => $output,
  );
  if (variable_get('fb_social_opengraph', 1)) {
    $content = drupal_get_title();
    $content = $content ? strip_tags($content) : variable_get('site_name', 'Drupal');

    //add fbml header meta information
    $element = array(
      '#tag' => 'meta',
      '#attributes' => array(
        'property' => 'og:title',
        'content' => $content,
      ),
    );
    drupal_add_html_head($element, 'fb_social_open_graph_title');
    $element = array(
      '#tag' => 'meta',
      '#attributes' => array(
        'property' => 'og:site_name',
        'content' => variable_get('site_name', 'Drupal'),
      ),
    );
    drupal_add_html_head($element, 'fb_social_open_graph_sitename');
  }

  /**
   * from facebook ..
   * If your site has many comments boxes, we strongly recommend you specify a Facebook app id
   * as the administrator (all administrators of the app will be able to moderate comments).
   * Doing this enables a moderator interface on Facebook where comments from all plugins
   * administered by your app id can be easily moderated together.
   */
  $element = array(
    '#tag' => 'meta',
    '#attributes' => array(
      'property' => 'fb:app_id',
      'content' => check_plain(variable_get('fb_social_appid', '')),
    ),
  );
  drupal_add_html_head($element, 'fb_social_fbadmin');
}

/**
 * @todo Please document this function.
 * @see http://drupal.org/node/1354
 */
function fb_social_auto_language() {
  return variable_get('fb_social_locale_auto', 0);
}
function _map_active_languages() {
  $languages = language_list();
  $mapped = array();
  foreach ($languages as $key => $language) {
    $mapped[$language->language] = variable_get('fb_social_language_' . $language->language, '');
  }
  return $mapped;
}

/**
 * The Custom Channel URL that FB.init has as an option
 */
function fb_social_custom_channel_url() {
  header("Cache-Control: public, s-maxage=31536000, max-age=31536000");
  header("Expires: Sun, 1 Oct 2079 00:00:00 GMT");
  global $language;
  $languages = _map_active_languages();
  $fb_locale = "en_US";
  if (fb_social_auto_language()) {
    if (array_key_exists($language->language, $languages)) {
      $fb_locale = $languages[$language->language];
    }
  }
  else {
    $fb_locale = variable_get('fb_social_locale', 'en_US');
  }
  print '<script src="http://connect.facebook.net/' . $fb_locale . '/all.js"></script>';
  exit;
}

// API functions

/**
 * Implementation of hook_fb_social_event_subscribe
 */
function fb_social_fb_social_event_subscribe() {

  // integration with google analytics
  if (module_exists('googleanalytics')) {
    global $user;
    $id = variable_get('googleanalytics_account', '');
    if (!empty($id) && _googleanalytics_visibility_pages() && _googleanalytics_visibility_user($user)) {
      return array(
        'FB.Event.subscribe("edge.create", function(href, widget) {',
        '_gaq.push(["_trackEvent", "Facebook like", "Drupal", href]);',
        '});',
      );
    }
  }
}

/**
 *  Based on the user settings return the aliased / unaliased version
 *  of a given $url
 *
 *  If option is selected, the base URL is rewritten to the specified value.
 *  If option is selected, the language tag is stripped from the URL.
 */
function fb_social_url($url = NULL) {
  $aliased = variable_get('fb_social_urls_mode', 0);
  $base_url = variable_get('fb_social_base_url', '');
  $strip_lang = variable_get('fb_social_url_strip_lang', 0);
  $url = url($url, array_filter(array(
    'absolute' => TRUE,
    'alias' => $aliased,
    'base_url' => $base_url,
  )));
  if ($strip_lang) {

    // i.e.  'http://www.mysite.nl/nl/node/xx' becomes 'http://www.mysite.nl/node/xx'
    global $language;
    $lang_tag = "/\\/" . $language->language . "/";
    $url = preg_replace($lang_tag, '', $url, 1);
  }
  return $url;
}

// helper functions

/**
 * Does $preset should be shown on node of type $type
 */
function fb_social_preset_node_types($preset, $node_type) {
  $types = $preset->settings['node_types']['types'];
  if (!is_array($types)) {
    return FALSE;
  }
  return !empty($types[$node_type]);
}

/**
* get nodes view modes
*/
function _fb_social_get_node_view_modes() {

  //get view modes
  $view_modes = array();
  $info = entity_get_info('node');
  foreach ($info['view modes'] as $k => $v) {
    $view_modes[$k] = $v['label'];
  }
  return $view_modes;
}

/**
 * Implements hook_views_api().
 */
function fb_social_views_api() {
  return array(
    'api' => 3,
  );
}

Functions

Namesort descending Description
fb_social_auto_language @todo Please document this function.
fb_social_block_info Implements hook_block_info().
fb_social_block_view Implements hook_block_view().
fb_social_boxes_plugins Implementation of hook_boxes_plugins().
fb_social_box_view returns the fbml content of the plugin
fb_social_ctools_plugin_api Implementation of hook_ctools_plugin_api().
fb_social_ctools_plugin_directory Implementation of hook_ctools_plugin_directory().
fb_social_ctools_plugin_type Implements hook_ctools_plugin_type() to inform the plugin system owns 'fb_plugin' plugin types.
fb_social_custom_channel_url The Custom Channel URL that FB.init has as an option
fb_social_fb_plugin_defaults Return the default vaules of a certain plugin type as defined by facebook
fb_social_fb_plugin_drupal_settings_form Return the drupal settings form for a given plugin type
fb_social_fb_plugin_fb_settings_form Return the facebook plugin form for a given type
fb_social_fb_plugin_load load a specific fb_plugin or all of them
fb_social_fb_social_event_subscribe Implementation of hook_fb_social_event_subscribe
fb_social_field_extra_fields Implements hook_content_extra_fields.
fb_social_get_presets Get all presets or a preset by name. By default it returns only enabled presets.
fb_social_get_presets_by_type
fb_social_link Fake hook_link (as in D6); for easy maintanance only
fb_social_menu Implements hook_menu().
fb_social_node_view Implements hook_node_view().
fb_social_page_alter Implements hook_page_alter().
fb_social_preprocess_fb_social_plugin Implements preprocess_hook
fb_social_preset_load load the preset
fb_social_preset_node_types Does $preset should be shown on node of type $type
fb_social_preset_view returns the fbml content of the plugin
fb_social_rdf_namespaces Implements hook_rdf_namespaces().
fb_social_theme Implementation of hook_theme
fb_social_url Based on the user settings return the aliased / unaliased version of a given $url
fb_social_views_api Implements hook_views_api().
_fb_social_ctools_plugin_fb_plugin_process Helper function for ctools plugin 'process'
_fb_social_enabled_presets_filter filter presets based on come conditions $args
_fb_social_get_node_view_modes get nodes view modes
_map_active_languages

Constants

Namesort descending Description
FB_REF_BASE_URL