You are here

function fb_canvas_process in Drupal for Facebook 6.2

Same name and namespace in other branches
  1. 5.2 fb_canvas.module \fb_canvas_process()
  2. 5 fb_canvas.module \fb_canvas_process()

This function uses regular expressions to convert links on canvas pages to URLs that begin http://apps.facebook.com/...

Call this method from themes when producing either FBML or iframe canvas pages. This is a relatively expensive operation. Its unfortunate that we must do it on every page request. However to the best of my knowledge, Drupal provides no better way.

In Drupal 7.x, there should be a way to alter URLs before they are rendered. That could provide a more efficient solution. Until then we are stuck with this.

Parameters

$output is the page (or iframe block) about to be returned.:

$options - 'add_target' will cause target=_top to be added: when producing an iframe. 'force_absolute_canvas' will turn relative urls for canvas pages into absolute, for use on profile tabs.

1 call to fb_canvas_process()
fb_canvas_fb in ./fb_canvas.module
Implementation of hook_fb().

File

./fb_canvas.module, line 742
This module provides support for Canvas page applications. Use Drupal to power traditional Facebook Apps.

Code

function fb_canvas_process($output, $options = array()) {
  global $base_url;
  global $_fb, $_fb_app;
  $patterns = array();
  $replacements = array();
  $base_path = base_path();
  if ($_fb) {
    if (function_exists('fb_url_outbound_alter')) {
      $base_before_rewrite = '';
      $rewrite_options = array();
      $base = $base_path . fb_url_outbound_alter($base_before_rewrite, $rewrite_options, '');

      // short URL with rewrite applied.
    }
    else {

      // Paving the way to make url alters optional.  (may not work properly)
      $base = $base_path;

      //print("in fb_canvas_process, base is '$base'.");
    }
    if (fb_canvas_is_fbml()) {

      //dpm($output, "before fb_canvas_process");

      // We're producing FBML for a canvas page
      // Fix for relative images
      $absolute_base = url('<front>', array(
        'absolute' => TRUE,
      ));
      $patterns[] = "|src=\"{$base}|";
      $replacements[] = "src=\"{$absolute_base}";

      // This fixes places in drupal that use base_url() . something, instead of calling url().
      // including links to stylesheets and such.
      $pattern = "|href=\"{$base}(?!" . preg_quote($_fb_app->canvas) . ")|";

      //print ("pattern is $pattern \n\n"); // debug
      $patterns[] = $pattern;
      $replacements[] = "href=\"{$absolute_base}";

      // This is needed under the old url rewriting scheme.
      // Hope to do away with this for good eventually!  XXX
      if (isset($options['force_absolute_canvas']) && $options['force_absolute_canvas'] && $base != '/') {

        // Change links to use canvas on Facebook
        // Links ending in #something:
        $patterns[] = "|=\"{$base}([^\"]*#)|";
        $replacements[] = "=\"http://apps.facebook.com/{$_fb_app->canvas}/\$1app{$_fb_app->id}_";

        // Other links
        $patterns[] = "|=\"{$base}|";
        $replacements[] = "=\"http://apps.facebook.com/{$_fb_app->canvas}/";
      }

      /*
      else {
        // Change links to use canvas on Facebook
        // Links ending in #something:
        $patterns[] = "|=\"{$base}([^\"]*#)|";
        $replacements[] = "=\"/{$_fb_app->canvas}/$1app{$_fb_app->id}_";
        // Other links
        $patterns[] = "|=\"{$base}|";
        $replacements[] = "=\"/{$_fb_app->canvas}/";
      }
      // Change paths to files to fully qualified URLs. This matches relative
      // URLs that do not include the canvas (that is, not matched by previous
      // patterns).
      if ($base_path != "/{$_fb_app->canvas}/") {
        $patterns[] = '|="'. $base_path . "(?!{$_fb_app->canvas})|";
        $replacements[] = '="'. $base_url .'/';
      }
      */

      // Experimental!  Change 1234@facebook to an <fb:name> tag.  This is our
      // default user name convention when creating new users.  Ideally, this
      // would be accomplished with something like:
      // http://drupal.org/node/102679.  In the meantime, this may help for
      // canvas pages only.
      // Regexp avoids "1234@facebook" (surrounded by quotes) because
      // that can appear in forms and FBML tags.  Also avoids
      // 1234@facebook.com, which can also appear in forms because it
      // is used in authmaps.  TODO: investigate the efficiency of
      // this regexp (and/or make it optional)
      $patterns[] = '|(?<!["\\d])([\\d]*)@facebook(?!\\.com)|';
      $replacements[] = '<fb:name uid=$1 linked=false ifcantsee="$1@facebook" useyou=false />';
    }
    elseif (fb_canvas_is_iframe()) {

      // Add target=_top so that entire pages do not appear within an iframe.
      // TODO: make these pattern replacements more sophisticated, detect whether target is already set.
      if (isset($options['add_target']) && $options['add_target']) {

        // Add target=_top to all links
        $patterns[] = "|<a ([^>]*)href=\"|";
        $replacements[] = "<a \$1 target=\"_top\" href=\"";

        // Do not change local forms, but do change external ones
        $patterns[] = "|<form([^>]*)action=\"([^:\"]*):|";
        $replacements[] = "<form target=\"_top\" \$1 action=\"\$2:";

        // Make internal links point to canvas pages
        $patterns[] = "|<a([^>]*)href=\"{$base}|";
        $replacements[] = "<a \$1 href=\"http://apps.facebook.com/{$_fb_app->canvas}/";
      }
      else {

        // Add target=_top to only external links
        $patterns[] = "|<a([^>]*)href=\"([^:\"]*):|";
        $replacements[] = "<a target=\"_top\" \$1 href=\"\$2:";
        $patterns[] = "|<form([^>]*)action=\"([^:\"]*):|";
        $replacements[] = "<form target=\"_top\" \$1 action=\"\$2:";
      }
    }
  }
  if (count($patterns)) {
    $count = 0;
    $return = preg_replace($patterns, $replacements, $output, -1, $count);

    //print ("fb_canvas_process replaced $count.\n\n"); // debug
    return $return;
  }
  else {
    return $output;
  }
}