<?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\">
     window.fbAsyncInit = function() {
       FB.init({
         appId: " . drupal_json_encode($appid) . ",
         status: true,
         cookie: true,
         xfbml: true,
         oauth : true,
         channelUrl: " . drupal_json_encode($channel_url) . "
         });
  
         ";
  // let each module subscribe to different events
  $output .= implode("\n", module_invoke_all('fb_social_event_subscribe'));
  $output .= "
     };
     (function() {
       var e = document.createElement('script');
       e.async = true;
       e.src = document.location.protocol + '//connect.facebook.net/" . $fb_locale . "/all.js';
       document.getElementById('fb-root').appendChild(e);
     }());
  </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  //url checks if this is set.  not what its value is.
  )));
  
  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,
  );
}
