Index: fb_navigation.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/fb_navigation.module,v
retrieving revision 1.1
diff -u -r1.1 fb_navigation.module
--- fb_navigation.module	4 Nov 2007 08:20:43 -0000	1.1
+++ fb_navigation.module	10 Nov 2007 08:32:45 -0000
@@ -65,9 +65,110 @@
             '#description' => t('Leave blank to use the site-wide front page.'),
             '#default_value' => $fb_navigation_data['front_added'],
       );
+    $form['fb_app_data']['fb_navigation']['callback_root'] =
+      array('#type' => 'textfield',
+            '#title' => t('Root for custom callbacks registered for this app.'),
+            '#description' => t('Leave blank to avoid registering any callbacks.'),
+            '#default_value' => $fb_navigation_data['callback_root'],
+      );
   }
   
 }
 
+/**
+ * Implements hook_menu, registering menu callbacks for all apps
+ */
+function fb_navigation_menu($may_cache) {
+
+  if ($may_cache) {
+    fb_app_fb(NULL, NULL, FB_OP_GET_ALL_APPS, &$apps, NULL);
+    foreach ($apps as $app) {
+      $data = fb_app_get_data($app);
+      $callback = $data['fb_navigation']['callback_root'];      
+      if ($callback) {
+        $items[] = array('path' => $callback,
+                         'callback' => 'fb_navigation_callback',
+                         'type' => MENU_CALLBACK,
+                         'access' => TRUE);
+      }
+    }
+  }
+  return $items;
+}
+
+/**
+ * Drupal menu callback: Wrapper around FB callback functions
+ */
+function fb_navigation_callback() {
+
+  // Get FB variables
+  global $fb, $fb_app;
+  $fb_user = $fb->user;
+  $fb_params = $fb->fb_params;
+
+  // Get canvas page & use it to find the function and build content
+  $canvas = $fb_app->canvas;
+  
+  $root = 'starfish_fb';
+  
+  $function_name = fb_navigation_get_function($root, $canvas);
+  $content = call_user_func($function_name, $fb_user, $fb_params);
+
+  // Try to theme content, if a theming function is defined (common app scaffolding)
+  $result = theme('fb_canvas_'.$canvas, $content);
+  if (!$result) $result = theme('fb_canvas_default', $content);
+  if (!$result) $result = $content;
+
+  // Return and exit
+  print $result;
+  exit();  
+}
+
+/**
+ * Finds the right callback function, based on canvas callbackand request args
+ */
+function fb_navigation_get_function($root, $canvas) {
+
+  // Process args and restore callback path
+  global $fb_path, $fb_args;
+  $args = explode('/', $_GET['q']); // e.g. $_GET[q] = fb/callback/share
+  unset($args[0]);
+  unset($args[1]);
+  $fb_path = $canvas.'/'.implode('/', $args);
+
+  // Look for callback function, if args defined
+  while (!empty($args)) {
+    // Construct and check function
+    $function_name = $root.'_'.$canvas."_".implode('_', $args); 
+    if (function_exists($function_name)) {
+      return $function_name;
+    } else {
+      $fb_args[] = array_pop($args); // pop an arg in reverse order
+    }
+  }
+  
+  // Try default canvas function
+  $function_name = $root.'_'.$canvas;  
+  if (function_exists($function_name)) return $function_name;
+
+  // No callback function defined, run default
+  return 'fb_navigation_default_function';
+}
+
+/**
+ * Default callback, if not set
+ */
+function fb_navigation_default_function() {
+
+  //TODO: Return a message telling developer to define a function
+
+}
+
+/**
+ * Default theming function
+ */
+function theme_fb_canvas_default($content) {
+  return $content;  
+}
 
 ?>
\ No newline at end of file
