You are here

fb_app.module in Drupal for Facebook 6.2

Same filename and directory in other branches
  1. 5.2 fb_app.module
  2. 5 fb_app.module
  3. 6.3 fb_app.module
  4. 7.3 fb_app.module

Implementation of Drupal for Facebook application.

For maximum flexibility, DFF allows multiple implementations of the "application" logic. The important bit is our implementation of hook_fb(). This module should suffice for just about everyone, but if you want to implement your own, go right ahead.

File

fb_app.module
View source
<?php

/**
 * @file
 * Implementation of Drupal for Facebook application.
 *
 * For maximum flexibility, DFF allows multiple implementations of the
 * "application" logic.  The important bit is our implementation of
 * hook_fb().  This module should suffice for just about everyone, but
 * if you want to implement your own, go right ahead.
 */
define('FB_APP_REQ_API_KEY', 'fb_sig_api_key');

// Events that a facebook app might need to know about:
define('FB_APP_EVENT_POST_AUTHORIZE', 'post_authorize');
define('FB_APP_EVENT_POST_REMOVE', 'post_remove');
define('FB_APP_PATH_EVENT', 'fb_app/event');
define('FB_APP_PATH_EVENT_ARGS', 2);
define('FB_APP_OP_EVENT', 'fb_app_event');

/**
 * Implementation of hook_fb().
 */
function fb_app_fb($op, $data, &$return) {
  $fb = isset($data['fb']) ? $data['fb'] : NULL;
  $fb_app = isset($data['fb_app']) ? $data['fb_app'] : NULL;
  if ($op == FB_OP_GET_APP) {

    // Load app data, using the criteria passed in.
    $args = array();
    $where = array();

    // This implementation uses 'label' as the unique id.
    foreach (array(
      FB_SETTINGS_CB,
      FB_SETTINGS_LABEL,
    ) as $key) {
      if (isset($data[$key]) && is_numeric($data[$key])) {

        // DEPRECATED
        // for backward compatibility we accept the nid, but that will go away in a later release!
        $where[] = "(label = '%s' || nid = '%d')";
        $args[] = $data[$key];
        $args[] = $data[$key];
      }
      elseif (isset($data[$key])) {

        // This is the right way, using label.
        $where[] = "label = '%s'";
        $args[] = $data[$key];
      }
    }

    // We also support these ways to query an app.
    foreach (array(
      'fba_id' => '%d',
      'apikey' => "'%s'",
      'nid' => '%d',
    ) as $key => $type) {
      if (isset($data[$key])) {
        $where[] = "{$key} = {$type}";
        $args[] = $data[$key];
      }
    }

    // Status is a special query.  Admin pages include disabled apps.
    if (isset($data['status'])) {
      $where[] = "status >= %d";
      $args[] = $data['status'];
    }
    else {
      $where[] = "status > 0";
    }
    if (count($args)) {
      $fb_app = db_fetch_object(db_query("SELECT * FROM {fb_app} fba WHERE " . implode(' AND ', $where), $args));
    }
    if ($fb_app) {
      $return = $fb_app;
    }
  }
  elseif ($op == FB_OP_GET_ALL_APPS) {

    // Return all known applications, including disabled.
    $result = db_query("SELECT fba.* FROM {fb_app} fba");
    while ($app = db_fetch_object($result)) {
      $return[] = $app;
    }
  }
  elseif ($op == FB_OP_POST_INIT) {

    // Include our admin hooks.
    if (fb_is_fb_admin_page()) {
      require drupal_get_path('module', 'fb_app') . '/fb_app.admin.inc';
    }
  }
  elseif ($op == FB_OP_CURRENT_APP) {

    // Normally the current app is determined by fb_canvas or fb_connect, unless it is our event callback.
    if (arg(0) == 'fb_app' && !$return) {
      if (function_exists('fb_settings')) {
        if (fb_settings(FB_SETTINGS_TYPE) == FB_SETTINGS_TYPE_CANVAS && ($apikey = fb_settings(FB_SETTINGS_APIKEY))) {
          $return = fb_get_app(array(
            'apikey' => $apikey,
          ));
        }
      }
    }
  }
}

/**
 * Implementation of hook_menu().
 */
function fb_app_menu() {
  $items = array();

  // Allow facebook to notify on various events, like adding or removing an app.
  $items[FB_APP_PATH_EVENT . '/%'] = array(
    'access callback' => TRUE,
    'page callback' => 'fb_app_event_cb',
    'page arguments' => array(
      FB_APP_PATH_EVENT_ARGS,
    ),
    'type' => MENU_CALLBACK,
  );

  // Administration.
  $items[FB_PATH_ADMIN . '/fb_app_create'] = array(
    'title' => 'Add Application',
    'description' => 'Host an application on this server.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'fb_app_edit_form',
    ),
    'access arguments' => array(
      FB_PERM_ADMINISTER,
    ),
    'file' => 'fb_app.admin.inc',
    'type' => MENU_LOCAL_TASK,
    'weight' => -1,
  );
  $items[FB_PATH_ADMIN_APPS . '/%fb/fb_app'] = array(
    'title' => 'Edit',
    'description' => 'Add Facebook Application',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'fb_app_edit_form',
      FB_PATH_ADMIN_APPS_ARGS,
    ),
    'access arguments' => array(
      FB_PERM_ADMINISTER,
    ),
    'file' => 'fb_app.admin.inc',
    'weight' => -1,
    'type' => MENU_LOCAL_TASK,
  );
  $items[FB_PATH_ADMIN_APPS . '/%fb/fb_app/delete'] = array(
    'title' => 'Delete',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'fb_app_admin_delete_confirm_form',
      FB_PATH_ADMIN_APPS_ARGS,
    ),
    'access arguments' => array(
      FB_PERM_ADMINISTER,
    ),
    'file' => 'fb_app.admin.inc',
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Callback for FB_APP_PATH_EVENT.
 * 
 * We don't act on the events directly.  We pass the information along via
 * hook_fb.  Other modules are thus notified of the event and can take action.
 */
function fb_app_event_cb($event_type) {

  // Events are passed 'fb_sig' params, so globals should be set.
  global $_fb, $_fb_app;
  if (!$_fb_app) {
    drupal_not_found();
    return;
  }
  watchdog('fb_app_event_cb', print_r($_REQUEST, 1));

  // debug
  watchdog('fb_app_event_cb', 'session id is ' . session_id());
  fb_invoke(FB_APP_OP_EVENT, array(
    'event_type' => $event_type,
    'fb_app' => $_fb_app,
    'fb' => $_fb,
  ), NULL);

  // This page is called by facebook, not a user's browser.  User's should never see this.
  print 'Thanks Facebook, for your fancy API!';

  // It's facebook calling us, not the user.  And fb_sig params make it look
  // like a canvas page, but it could be connect.  So bad idea to save session.
  session_save_session(FALSE);
  exit;
}
function fb_app_get_about_url($fb_app) {
  if ($fb_app->id) {
    return url("http://www.facebook.com/apps/application.php", array(
      'query' => array(
        'id' => $fb_app->id,
      ),
    ));
  }
}

// Not currently used, AFAIK.
function theme_fb_app($fb_app) {

  // Get known properties
  $props_map = fb_invoke(FB_OP_LIST_PROPERTIES, array(
    'fb_app' => $fb_app,
  ), array());
  $data = array(
    t('Label') => $fb_app->label,
    t('API Key') => $fb_app->apikey,
  );
  foreach ($props_map as $name => $key) {
    if (isset($fb_app->{$key})) {
      $data[$name] = $fb_app->{$key};
    }
  }
  $output = theme('dl', $data);
  return $output;
}

/**
 * Implementation of hook_user.
 */
function fb_app_user($op, &$edit, &$account, $category = NULL) {
  $items = array();
  if ($op == 'view') {
    $apps = fb_get_all_apps();
    foreach ($apps as $fb_app) {

      // Learn this user's FB id
      $fbu = fb_get_fbu($account->uid, $fb_app);
      if ($fbu) {

        // The drupal user is a facebook user.  Now, learn more from facebook.
        $fb = fb_api_init($fb_app, FB_FBU_ANY);
        if (fb_facebook_user($fb)) {
          try {
            $info = $fb->api_client
              ->users_getInfo(array(
              $fbu,
            ), array(
              'about_me',
              'affiliations',
              'name',
              'is_app_user',
              'pic_big',
              'profile_update_time',
              'status',
            ));
          } catch (Exception $e) {
            fb_log_exception($e, "Failed to get Facebook user info for account {$fbu}");
          }
        }
        if (isset($info) && count($info)) {

          // Is this working properly??? TODO!
          $output = theme('fb_app_user_info', $fb_app, $info[0]);
          $items[$fb_app->label] = array(
            'title' => $fb_app->title,
            'value' => $output,
            'class' => 'fb_app',
          );
        }
        else {
          fb_report_errors($fb);
        }
      }
    }
    if (count($items)) {
      return array(
        t('Facebook') => $items,
      );
    }
  }
}
function theme_fb_app_user_info($fb_app, $info) {
  if (isset($info['pic_big'])) {
    $output = '<p><img src="' . $info['pic_big'] . '" /></p>';
  }
  $fb_link = l($info['name'], 'http://www.facebook.com/profile.php', array(
    'query' => 'id=' . $info['uid'],
  ));
  if ($info['is_app_user']) {
    $output .= '<p>' . t('!fb_link uses %title', array(
      '!fb_link' => $fb_link,
      '%title' => $fb_app->title,
    )) . '</p>';
  }
  else {
    $output .= '<p>' . t('!fb_link does not use %title', array(
      '!fb_link' => $fb_link,
      '%title' => $fb_app->title,
    )) . '</p>';
  }
  return $output;
}
function fb_app_token_list($type = 'all') {
  if ($type == 'all' || $type == 'fb' || $type == 'fb_app') {
    $tokens['fb_app']['fb-app-label'] = t('Facebook application label');
    $tokens['fb_app']['fb-app-url'] = t('Facebook application canvas page URL');
  }
  return $tokens;
}
function fb_app_token_values($type = 'all', $object = NULL) {
  $values = array();
  if ($type == 'fb_app' && $object) {
    $fb_app = $object;
    $values['fb-app-label'] = $fb_app->label;
    $values['fb-app-url'] = 'http://apps.facebook.com/' . $fb_app->canvas;
  }
  return $values;
}

Functions

Namesort descending Description
fb_app_event_cb Callback for FB_APP_PATH_EVENT.
fb_app_fb Implementation of hook_fb().
fb_app_get_about_url
fb_app_menu Implementation of hook_menu().
fb_app_token_list
fb_app_token_values
fb_app_user Implementation of hook_user.
theme_fb_app
theme_fb_app_user_info

Constants