You are here

fb_app.module in Drupal for Facebook 5

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

Defines a custom node type that stores a facebook application configuration.

File

fb_app.module
View source
<?php

/**
 * @file
 *   Defines a custom node type that stores a facebook application configuration.
 */
define('FB_APP_REQ_API_KEY', 'fb_sig_api_key');

/**
 * hook_fb
 */
function fb_app_fb($fb, $fb_app, $op, &$return, $data) {

  //drupal_set_message("fb_app_fb($fb_app->label, $op)" . dpr($fb_app, 1));
  if ($op == FB_OP_GET_APP) {

    // This operation determines which app the request is for.  Theoretically,
    // the allows fb_app and other app-defining modules to co-exist.  We need
    // to determine if the app is one of ours and if so, return the app
    // details.
    // If apikey or nid was passed to us, use that
    if ($data['nid']) {
      $fb_app = db_fetch_object(db_query("SELECT * FROM {fb_app} fb INNER JOIN {node} n ON n.nid=fb.nid WHERE fb.nid=%d and status=1", $data['nid']));
    }
    else {
      if ($data['apikey']) {
        $fb_app = db_fetch_object(db_query("SELECT * FROM {fb_app} fb INNER JOIN {node} n ON n.nid=fb.nid WHERE apikey='%s' and status=1", $data['apikey']));
      }
      else {
        if ($apikey = $_REQUEST[FB_APP_REQ_API_KEY]) {

          // If facebook has passed the app key, let's use that.
          $fb_app = db_fetch_object(db_query("SELECT * FROM {fb_app} fb INNER JOIN {node} n ON n.nid=fb.nid WHERE apikey='%s' and status=1", $apikey));
        }
        else {
          if (function_exists('fb_settings')) {

            // See settings.inc
            if ($nid = fb_settings(FB_SETTINGS_APP_NID)) {

              // Here if we're in iframe, using our /fb_canvas/nid/ path convention.
              $fb_app = db_fetch_object(db_query("SELECT * FROM {fb_app} fb INNER JOIN {node} n ON n.nid=fb.nid WHERE fb.nid=%d and status=1", $nid));
            }
          }
        }
      }
    }
    if ($fb_app) {
      $return = $fb_app;
    }

    // If we didn't find the app, maybe someone else has written a module that
    // stores app info in a different way.
  }
  else {
    if ($op == FB_OP_GET_ALL_APPS) {

      // Return all known applications
      $result = _fb_app_query_all();
      while ($app = db_fetch_object($result)) {
        $return[] = $app;
      }
    }
    else {
      if ($op == FB_OP_INITIALIZE) {

        // User init has been moved to fb_user.module.
        // For now, nothing to do here.
      }
      else {
        if ($op == FB_OP_POST_INIT) {

          /* TODO: move this feature to an explicit setting.  For now, we just use site homepage
             // Here we override the front_page settings
             if ($_REQUEST['q'] == '' && $fb_app->nid) {
               menu_set_active_item('node/'.$fb_app->nid);
               // Note, menu_set_active_item only works as intended if fb.module
               // is weighted lighter than node.module!
             }
               */
        }
      }
    }
  }
}

/**
 * hook_node_info.
 */
function fb_app_node_info() {
  return array(
    'fb_app' => array(
      'name' => t('Facebook Application'),
      'module' => 'fb_app',
      'description' => t('Information such as apikey and secret for a facebook.com application.'),
      'help' => t('Configure the behavior of your Facebook Application.'),
    ),
  );
}
function fb_app_access($op, $node) {
  if (user_access('administer fb apps')) {
    return TRUE;
  }
  if ($op == 'create' && user_access('create fb apps')) {
    return TRUE;
  }
  else {
    if ($op == 'update' || $op == 'delete') {
      if ($node->uid == $user->uid && user_access('edit own fb apps')) {
        return TRUE;
      }
    }
  }
}
function fb_app_perm() {
  return array(
    'administer fb apps',
    'create fb apps',
    'edit own fb apps',
  );
}
function fb_app_form(&$node, &$param) {

  // Helpful link
  if (!$node->nid) {
    drupal_set_message(t("Before completing this form, <a href=!url>create your application</a> on Facebook.", array(
      '!url' => 'http://www.facebook.com/developers/editapp.php?new',
    )));
  }
  $form = array();
  $type = node_get_types('type', $node);

  // We need to define form elements for the node's title and body.
  $form['title'] = array(
    '#type' => 'textfield',
    '#title' => check_plain($type->title_label),
    '#required' => TRUE,
    '#default_value' => $node->title,
    '#weight' => -5,
    '#description' => t('Identifies the application to site administrators.'),
  );

  // We want the body and filter elements to be adjacent. We could try doing
  // this by setting their weights, but another module might add elements to the
  // form with the same weights and end up between ours. By putting them into a
  // sub-array together, we're able force them to be rendered together.
  $form['body_filter']['body'] = array(
    '#type' => 'textarea',
    '#title' => check_plain($type->body_label),
    '#default_value' => $node->body,
    '#required' => FALSE,
    '#description' => 'Not sure yet how this will be used.',
  );
  $form['body_filter']['filter'] = filter_form($node->format);

  // Now we define the form elements specific to our node type.
  $form['fb_app'] = array(
    '#tree' => TRUE,
    '#weight' => -4,
  );
  $form['fb_app']['label'] = array(
    '#type' => 'textfield',
    '#title' => t('Label'),
    '#required' => TRUE,
    '#default_value' => $node->fb_app->label,
    '#description' => t('Used behind the scenes, for naming roles, styles, etc.  Use no spaces or weird characters.'),
  );
  $form['fb_app']['apikey'] = array(
    '#type' => 'textfield',
    '#title' => t('API Key'),
    '#required' => TRUE,
    '#default_value' => $node->fb_app->apikey,
    '#description' => t('Facebook will generate this value when you create the application.'),
  );
  $form['fb_app']['secret'] = array(
    '#type' => 'textfield',
    '#title' => t('Secret'),
    '#required' => TRUE,
    '#default_value' => $node->fb_app->secret,
    '#description' => t('Facebook will generate this value when you create the application.'),
  );
  $form['fb_app']['canvas'] = array(
    '#type' => 'textfield',
    '#title' => t('Canvas Page Url Suffix'),
    '#required' => TRUE,
    '#default_value' => $node->fb_app->canvas,
    '#description' => t('Type only the part that comes after "http://apps.facebook.com/"'),
  );
  $form['fb_app']['id'] = array(
    '#type' => 'textfield',
    '#title' => t('Facebook App ID'),
    '#required' => FALSE,
    '#default_value' => $node->fb_app->id,
    '#description' => t('To learn this number, visit your app\'s About Page (or other links from Facebook\'s Developer App).  The URL will end in ?id=1234...  Enter the number that follows "?id=" here.'),
  );

  // fb_app_data is a placeholder to make it easier for other module to attach
  // various settings to the node.
  $form['fb_app_data'] = array(
    '#tree' => TRUE,
  );

  // TODO: move this to another module, or get rid of it entirely.

  /* XXX This needs to be re-thought.  Disabling for now.
    $form['fb_app_blocks'] = array('#tree' => TRUE);
    for ($i = 0; $i < _fb_app_num_blocks(); $i++) {
      $form['fb_app_blocks'][$i]['body'] =
        array('#type' => 'textarea',
              '#title' => t('Block !num', array('!num' => $i+1)),
              '#default_value' => $node->fb_app_blocks[$i]->body,
              '#required' => FALSE,
              '#description' => t('Enter markup to be used as this application\'s navigation.  Typically this is an unordered list of links.'),
        );
      $form['fb_app_blocks'][$i]['format'] = filter_form($node->fb_app_blocks[$i]->format,
                                                         NULL,
                                                         array('fb_app_blocks', $i, 'format'));

    }
    */
  return $form;
}
function fb_app_validate($node) {

  // TODO: check label is unique, and role name will be unique.
  // check apikey is unique, canvas page is unique
  // check no menu items start with $fb_app->canvas, because we will rewrite those URLs
}
function fb_app_load($node) {
  $fb_app = db_fetch_object(db_query('SELECT * FROM {fb_app} WHERE nid=%d', $node->nid));
  $fb_app_data = fb_app_get_data($fb_app);
  $result = db_query('SELECT * FROM {fb_app_block} WHERE nid=%d', $node->nid);
  while ($data = db_fetch_object($result)) {
    $blocks[$data->delta] = $data;
  }
  return array(
    'fb_app' => $fb_app,
    'fb_app_blocks' => $blocks,
    'fb_app_data' => $fb_app_data,
  );
}
function fb_app_view($node, $teaser = FALSE, $page = FALSE) {
  $node = node_prepare($node, $teaser);

  // Perhaps this info should be hidden, unless user can edit node.
  if (user_access('administer fb apps')) {
    $node->content['fb_app'] = array(
      '#value' => theme('fb_app', $node->fb_app),
      '#weight' => 1,
    );
    if (count($node->fb_app_blocks)) {
      foreach ($node->fb_app_blocks as $delta => $data) {
        $node->content['fb_app_blocks'][$delta] = array(
          'subject' => array(
            '#value' => t('Block %num', array(
              '%num' => $delta + 1,
            )),
          ),
          'content' => array(
            '#value' => check_markup($data->body, $data->format, FALSE),
            '#weight' => 1,
          ),
        );
      }
    }
    $node->content['fb_app_blocks']['#weight'] = 10;
  }
  return $node;
}
function fb_app_get_about_url($fb_app) {
  if ($fb_app->id) {
    return url("http://www.facebook.com/apps/application.php", "id={$fb_app->id}");
  }
}
function theme_fb_app($data) {
  $about_url = fb_app_get_about_url($data);
  return theme('dl', array(
    t('Label') => $data->label,
    t('API Key') => $data->apikey,
    t('Secret') => $data->secret,
    t('About page') => $about_url ? $about_url : t('N/A'),
  ));
}

// this belongs elsewhere
function theme_dl($items) {
  if (count($items)) {
    $output = "<dl>\n";
    foreach ($items as $term => $data) {
      $output .= "  <dt>{$term}</dt><dd>{$data}</dd>\n";
    }
    $output .= "</dl>\n";
    return $output;
  }
}
function fb_app_insert($node) {

  //drupal_set_message("fb_app_insert" . dpr($node,1));
  $fb_app = (object) $node->fb_app;
  $data = serialize($node->fb_app_data);
  db_query("INSERT INTO {fb_app} (nid, label, apikey, secret, id, canvas, require_login, create_account, unique_account, data) VALUES (%d, '%s', '%s', '%s', '%s', '%s', %d, %d, %d, '%s')", $node->nid, $fb_app->label, $fb_app->apikey, $fb_app->secret, $fb_app->id, $fb_app->canvas, $fb_app->require_login, $fb_app->create_account, $fb_app->unique_account, $data);
  _fb_app_blocks_update($node);
  watchdog('fb_app', t('Created Facebook Application %label.', array(
    '%label' => $fb_app->label,
  )), WATCHDOG_NOTICE, l($node->title, 'node/' . $node->nid));
}
function _fb_app_blocks_update($node) {
  db_query('DELETE FROM {fb_app_block} WHERE nid=%d', $node->nid);
  if (count($node->fb_app_blocks)) {
    foreach ($node->fb_app_blocks as $delta => $data_array) {
      $data = (object) $data_array;

      //if (!$delta)

      //  $delta = '0';
      db_query("INSERT INTO {fb_app_block} (nid, delta, body, format) VALUES (%d, '%s', '%s', %d)", $node->nid, $delta, $data->body, $data->format);
    }
  }
}
function fb_app_update($node) {
  $fb_app = (object) $node->fb_app;
  $data = serialize($node->fb_app_data);
  db_query("UPDATE {fb_app} SET label='%s', apikey='%s', secret='%s', id='%s', canvas='%s', require_login=%d, create_account=%d, unique_account=%d, data='%s' WHERE nid=%d", $fb_app->label, $fb_app->apikey, $fb_app->secret, $fb_app->id, $fb_app->canvas, $fb_app->require_login, $fb_app->create_account, $fb_app->unique_account, $data, $node->nid);
  _fb_app_blocks_update($node);
}
function fb_app_delete($node) {
  db_query('DELETE FROM {fb_app} WHERE nid=%d', $node->nid);
  db_query('DELETE FROM {fb_app_block} WHERE nid=%d', $node->nid);
}

/**
 * Convenience method for other modules to attach data to the fb_app object.
 */
function fb_app_get_data(&$fb_app) {
  if (!$fb_app->fb_app_data) {
    $fb_app->fb_app_data = unserialize($fb_app->data);
  }
  return $fb_app->fb_app_data;
}
function _fb_app_num_blocks() {
  return variable_get('fb_app_num_blocks', 1);
}
function fb_app_block($op = 'list', $delta = 0, $edit = array()) {
  if ($op == 'list') {
    for ($i = 0; $i < _fb_app_num_blocks(); $i++) {
      $items[$i]['info'] = t('Facebook Application block !num', array(
        '!num' => $i + 1,
      ));
    }
    return $items;
  }
  else {
    if ($op == 'view') {
      global $fb_app;
      $result = db_query("SELECT * FROM {fb_app_block} WHERE nid=%d AND delta='%s'", $fb_app->nid, $delta);
      $data = db_fetch_object($result);
      if ($data) {
        $output = check_markup($data->body, $data->format, FALSE);
        return array(
          'content' => $output,
        );
      }
    }
  }
}

/**
 * Helper function returns a database query for all apps.
 */
function _fb_app_query_all() {
  $result = db_query("SELECT fb.*, n.title FROM {fb_app} fb INNER JOIN {node} n ON n.nid=fb.nid WHERE status=1");
  return $result;
}
function _fb_app_query_by_label($label) {
  $result = db_query("SELECT fb.*, n.title FROM {fb_app} fb INNER JOIN {node} n ON n.nid=fb.nid WHERE n.status=1 AND fb.label = '%s'", $label);
  return $result;
}

/**
 * Implementation of hook_user.
 */
function fb_app_user($op, &$edit, &$account, $category = NULL) {
  $items = array();
  if ($op == 'view') {
    $result = _fb_app_query_all();
    while ($fb_app = db_fetch_object($result)) {

      // 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)) {
          $info = $fb->api_client
            ->users_getInfo(array(
            $fbu,
          ), array(
            'about_me',
            'affiliations',
            'name',
            'is_app_user',
            'pic_big',
            'profile_update_time',
            'status',
          ));
        }
        if (count($info)) {
          $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 ($info['pic_big']) {
    $output .= '<p><img src="' . $info['pic_big'] . '" /></p>';
  }
  $fb_link = l($info['name'], 'http://www.facebook.com/profile.php', NULL, '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-nid'] = t('Facebook application ID');
    $tokens['fb_app']['fb-app-title'] = t('Facebook application title');
    $tokens['fb_app']['fb-app-url'] = t('Facebook application URL (base path)');
  }
  return $tokens;
}
function fb_app_token_values($type = 'all', $object = NULL) {
  if ($type == 'fb_app' && $object) {
    $fb_app = $object;
    $values['fb-app-title'] = $fb_app->title;
    $values['fb-app-nid'] = $fb_app->nid;
    $values['fb-app-url'] = 'http://apps.facebook.com/' . $fb_app->canvas;
  }
  return $values;
}

Functions

Constants

Namesort descending Description
FB_APP_REQ_API_KEY @file Defines a custom node type that stores a facebook application configuration.