You are here

fb_views.module in Drupal for Facebook 5

Same filename and directory in other branches
  1. 5.2 fb_views.module

File

fb_views.module
View source
<?php

function fb_views_views_tables() {

  // The fb_user_app table allows us to associate a node author's uid to a
  // facebook id.
  // Will be present if fb_user.module is used.
  // This might need to be improved to take the apikey into account (for sites that host more than one app.)
  $tables['fb_user_app'] = array(
    'name' => 'fb_user_app',
    'join' => array(
      'left' => array(
        'table' => 'node',
        'field' => 'uid',
      ),
      'right' => array(
        'field' => 'uid',
      ),
    ),
  );
  return $tables;
}
function fb_views_views_arguments() {
  $items['fb_user_author'] = array(
    'name' => t('Facebook User: Author is Friend'),
    'help' => t('The node\'s author is a friend of the user.  <br/>The application hint is needed on non-canvas pages, ignored on canvas pages.'),
    'handler' => 'fb_views_handler_author_is_friend',
    'option' => array(
      '#type' => 'select',
      '#options' => fb_get_app_options(FALSE),
      '#title' => t('App Hint'),
    ),
  );
  return $items;
}
function fb_views_handler_author_is_friend($op, &$query, $a1, $a2 = null) {

  //dpm(func_get_args(), "fb_views_handler_author_is_friend");

  // For convenience, allow 'current' for current user
  if ($a2 == 'current') {
    global $user;
    $a2 = $user->uid;
  }
  if ($op == 'summary') {

    // Ideally, we'd display all users who are known facebook users.  However, because the primary table is node, we can only show those who have actually posted content.
    $query
      ->add_table('fb_user_app', TRUE);
    $query
      ->add_where('fb_user_app.uid IS NOT NULL');
    $query
      ->add_table('users', true);
    $query
      ->add_field('name', 'users');
    $query
      ->add_field('uid', 'users');
    $fieldinfo['field'] = "users.name";
    return $fieldinfo;
  }
  else {
    if ($op == 'filter') {
      $fb_app = $GLOBALS['fb_app'];

      // Canvas pages only.
      if (!$fb_app) {
        $fb_app = fb_get_app(array(
          'nid' => $a1['options'],
        ));
      }
      $uid = intval($a2);
      $fbu = fb_get_fbu($uid, $fb_app);
      $friends = array();

      // On non-canvas pages, we have to work harder to get the facebook id.
      if ($uid && !$fbu) {

        // This code may never be reached.
        $result = db_query("SELECT fbu FROM {fb_user_app} WHERE uid='%d'", $uid);
        while ($data = db_fetch_object($result)) {
          $friends = array_merge($friends, fb_get_friends($data->fbu));
        }
      }
      else {
        $friends = fb_get_friends($fbu, $fb_app);
      }
      if (is_array($friends) && count($friends)) {
        $query
          ->add_table('fb_user_app', TRUE);
        $query
          ->add_where('fb_user_app.fbu IN (%s)', implode(',', $friends));
      }
      else {

        // No friends found.  How best to handle this?
        $query
          ->add_where('0');
      }
    }
    else {
      if ($op == 'link') {
        return l($query->name, "{$a2}/" . intval($query->uid));
      }
      else {
        if ($op == 'title') {
          if ($query == 'current') {
            global $user;
            $query = $user->uid;
          }
          $data = db_fetch_object(db_query("SELECT name FROM {users} WHERE uid = '%d'", $query));
          return check_plain($data->name);
        }
      }
    }
  }
}

/**
 * Introduce a theme style that mimics a facebook discussion board.
 * 
 * To use: make a theme which provides a page view, and select view type
 * 'Facebook Discussion'.  Then under Fields, include Node: Title, Node:
 * Created Time, Node: Author Name, Comment: Count, Comment: Last Comment
 * Author, Comment: Last Comment Time.
 * 
 * It may not look exactly like a facebook discussion, but comes close.
 */
function fb_views_views_style_plugins() {
  $items = array();
  $items['fb_discussion'] = array(
    'name' => t('Facebook Discussion'),
    'theme' => 'views_fb_discussion',
    'summary_theme' => 'views_summary',
    'needs_table_header' => true,
    'needs_fields' => TRUE,
  );
  $items['fb_teasers'] = array(
    'name' => t('Facebook Teaser List'),
    'theme' => 'views_fb_teasers',
    'summary_theme' => 'views_summary',
    'needs_table_header' => true,
    'needs_fields' => TRUE,
  );
  return $items;
}
function theme_views_fb_discussion($view, $nodes, $type) {

  //drupal_set_message("theme_views_fb_discussion, type is '$type'" . dprint_r($view, 1) . dprint_r($nodes, 1));  // debug
  if ($type == 'page') {

    // use tablesort code to generate the sort links.
    $sorts = array();
    $ts = tablesort_init($view->table_header);
    foreach ($view->table_header as $cell) {
      $th = tablesort_header($cell, $view->table_header, $ts);
      $sorts[] = $th['data'];
    }
    $output .= theme('sortable_header_links', $sorts);
    $output .= theme('fb_discussion_nodes', $view, $nodes);
  }
  else {
    if ($type == 'block') {

      // If were displaying in a block, its most likely the profile page, where
      // all styles have to be inline.  So here we do our best to mimic the
      // block view of a facebook discussion.
      foreach ($nodes as $data) {
        $reply_count = format_plural($data->node_comment_statistics_comment_count + 1, '1 post', '@count posts');
        $output .= '<div style="padding: 10px 20px 10px 5px; border-bottom: 1px solid #cccccc;">';
        $output .= '<div style="font-weight: bold; font-size: 10px;">' . l($data->node_title, 'node/' . $data->nid, array(), NULL, NULL, FALSE) . "</div><div style=\"font-size: 9px;\"><span style=\"color: #333333;\">{$reply_count}</span><span style=\"color: #888888; margin-left: 5px;\">Updated " . format_interval(time() - $data->node_comment_statistics_last_comment_timestamp) . " ago.</span></div>\n";
        $output .= "</div>\n";
      }
    }
  }
  return $output;
}
function theme_sortable_header_links($items = array()) {
  if (!empty($items)) {
    $output .= "<ul class=\"links sortable_header_links\">";
    $output .= "<li class=\"first\">" . t('Sort by') . '</li>';
    foreach ($items as $item) {
      $output .= '<li>' . $item . '</li>';
    }
    $output .= "</ul>";
  }
  return $output;
}
function theme_fb_discussion_nodes($view, $items = array()) {
  $fields = _views_get_fields();
  if (!empty($items)) {
    foreach ($items as $item) {
      $out = array();
      $row = array();
      foreach ($view->field as $field) {
        if ($fields[$field['id']]['visible'] !== FALSE) {
          $out[$field['field']] = views_theme_field('views_handle_field', $field['queryname'], $fields, $field, $item, $view);
        }
      }
      $reply_count = format_plural($item->node_comment_statistics_comment_count + 1, '1 post', '@count posts');

      // Title link, reply count and created date
      $row[] = array(
        'class' => 'fb_discussion_topic',
        'data' => '<div class="title">' . $out['title'] . '</div>' . '<div class="info"><span class="post">' . $reply_count . '.</span>&nbsp;<span class="created">' . t('Created !time', array(
          '!time' => $out['created'],
        )) . '.</span></div>',
      );

      // Most recent reply info
      $row[] = array(
        'class' => 'fb_discussion_reply',
        'data' => '<div class="author">' . t('Latest post by !name', array(
          '!name' => $out['last_comment_name'],
        )) . '</div><div class="timestamp">' . $out['last_comment_timestamp'] . '</div>',
      );
      $rows[] = $row;
    }
    if (count($rows)) {
      $output = theme('table', array(), $rows, array(
        'class' => 'fb_discussion',
      ));
    }
  }
  return $output;
}
function theme_views_fb_teasers($view, $nodes, $type) {

  //drupal_set_message("theme_views_fb_teasers, type is '$type'" . dprint_r($view, 1) . dprint_r($nodes, 1));  // debug

  // If were displaying in a block, its most likely the profile page, where
  // all styles have to be inline.  So here we do our best to mimic the
  // block view of a facebook discussion.
  foreach ($nodes as $data) {
    $node = node_load($data->nid);
    $output .= '<div style="padding: 10px 20px 10px 5px; border-bottom: 1px solid #cccccc;">';
    $output .= '<div style="font-weight: bold; font-size: 10px;">' . l($node->title, 'node/' . $data->nid, array(), NULL, NULL, FALSE) . "</div>";
    $node = node_build_content($node, TRUE, FALSE);
    $output .= drupal_render($node->content);
    $output .= "</div>\n";
  }
  return $output;
}