Index: contrib/fb_permission.all_permissions.inc
===================================================================
RCS file: contrib/fb_permission.all_permissions.inc
diff -N contrib/fb_permission.all_permissions.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ contrib/fb_permission.all_permissions.inc	7 Aug 2010 09:24:51 -0000
@@ -0,0 +1,195 @@
+<?php
+// $Id$
+/**
+ * @file
+ * Function with array of all available facebook permissions.
+ * see http://wiki.developers.facebook.com/index.php/Extended_permissions
+ */
+
+/**
+ * List of all available permissions
+ */
+function fb_permission_list_all_permissions() {
+  static $perms;
+  if (!isset($perms)) {
+    $perms = array(
+        'publishing' => array(
+          array(
+            'label' => t('Stream'),
+            'permissions' => array('publish_stream'),
+            'description' => t("Enables your application to post content, comments, and likes to a user's stream and to the streams of the user's friends, without prompting the user each time."),
+          ),
+          array(
+            'label' => t('Event'),
+            'permissions' => array('create_event'),
+            'description' => t("Enables your application to create and modify events on the user's behalf"),
+          ),
+          array(
+            'label' => t('RSVP'),
+            'permissions' => array('rsvp_event'),
+            'description' => t("Enables your application to RSVP to events on the user's behalf"),
+          ),
+          array(
+            'label' => t('SMS'),
+            'permissions' => array('sms'),
+            'description' => t("Enables your application to send messages to the user and respond to messages from the user via text message"),
+          ),
+          array(
+            'label' => t('Offline access'),
+            'permissions' => array('offline_access'),
+            'description' => t("Enables your application to perform authorized requests on behalf of the user at any time. By default, most access tokens expire after a short time period to ensure applications only make requests on behalf of the user when the are actively using the application. This permission makes the access token returned by our OAuth endpoint long-lived"),
+          ),
+        ),
+        'page' => array(
+          array(
+            'label' => t('Manage pages'),
+            'permissions' => array('manage_pages'),
+            'description' => t('Enables your application to retrieve access_tokens for pages the user administrates. The access tokens can be queried using the "accounts" connection in the Graph API. This permission is only compatible with the Graph API.'),
+          ),
+        ),
+        'data' => array(
+          array(
+            'label' => t('Email'),
+            'permissions' => array('email'),
+            'description' => t("Provides access to the user's primary email address in the email property. Do not spam users. Your use of email must comply both with Facebook policies and with the CAN-4 Act."),
+          ),
+          array(
+            'label' => t('Insights'),
+            'permissions' => array('read_insights'),
+            'description' => t("Provides read access to the Insights data for pages, applications, and domains the user owns."),
+          ),
+          array(
+            'label' => t('Stream'),
+            'permissions' => array('read_stream'),
+            'description' => t("Provides access to all the posts in the user's News Feed and enables your application to perform searches against the user's News Feed"),
+          ),
+          array(
+            'label' => t('Mailbox'),
+            'permissions' => array('read_mailbox'),
+            'description' => t("Provides the ability to read from a user's Facebook Inbox. You must request to be whitelisted before you can prompt for this permission."),
+          ),
+          array(
+            'label' => t('Ads'),
+            'permissions' => array('ads_management'),
+            'description' => t("Provides the ability to manage ads and call the Facebook Ads API on behalf of a user."),
+          ),
+          array(
+            'label' => t('XMPP login'),
+            'permissions' => array('xmpp_login'),
+            'description' => t("Provides applications that integrate with Facebook Chat the ability to log in users."),
+          ),
+          array(
+            'label' => t('About Me'),
+            'permissions' => array('user_about_me', 'friends_about_me'),
+            'description' => t('Provides access to the "About Me" section of the profile in the about property'),
+          ),
+          array(
+            'label' => t('Activities'),
+            'permissions' => array('user_activities', 'friends_activities'),
+            'description' => t("Provides access to the user's list of activities as the activities connection"),
+          ),
+          array(
+            'label' => t('Birthday'),
+            'permissions' => array('user_birthday', 'friends_birthday'),
+            'description' => t("Provides access to the full birthday with year as the birthday_date property"),
+          ),
+          array(
+            'label' => t('Education history'),
+            'permissions' => array('user_education_history', 'friends_education_history'),
+            'description' => t("Provides access to education history as the education property"),
+          ),
+          array(
+            'label' => t('Events'),
+            'permissions' => array('user_events', 'friends_events'),
+            'description' => t("Provides access to the list of events the user is attending as the events connection"),
+          ),
+          array(
+            'label' => t('Groups'),
+            'permissions' => array('user_groups', 'friends_groups'),
+            'description' => t("Provides access to the list of groups the user is a member of as the groups connection"),
+          ),
+          array(
+            'label' => t('Hometown'),
+            'permissions' => array('user_hometown', 'friends_hometown'),
+            'description' => t("Provides access to the user's hometown in the hometown property"),
+          ),
+          array(
+            'label' => t('Interests'),
+            'permissions' => array('user_interests', 'friends_interests'),
+            'description' => t("Provides access to the user's list of interests as the interests connection"),
+          ),
+          array(
+            'label' => t('Likes'),
+            'permissions' => array('user_likes', 'friends_likes'),
+            'description' => t("Provides access to the list of all of the pages the user has liked as the likes connection"),
+          ),
+          array(
+            'label' => t('Location'),
+            'permissions' => array('user_location', 'friends_location'),
+            'description' => t("Provides access to the user's current location as the current_location property"),
+          ),
+          array(
+            'label' => t('Notes'),
+            'permissions' => array('user_notes', 'friends_notes'),
+            'description' => t("Provides access to the user's notes as the notes connection"),
+          ),
+          array(
+            'label' => t('Online presence'),
+            'permissions' => array('user_online_presence', 'friends_online_presence'),
+            'description' => t("Provides access to the user's online/offline presence"),
+          ),
+          array(
+            'label' => t('Photo and video tags'),
+            'permissions' => array('user_photo_video_tags', 'friends_photo_video_tags'),
+            'description' => t("Provides access to the photos the user has been tagged in as the photos connection"),
+          ),
+          array(
+            'label' => t('Photos'),
+            'permissions' => array('user_photos', 'friends_photos'),
+            'description' => t("Provides access to the photos the user has uploaded"),
+          ),
+          array(
+            'label' => t('Relationships'),
+            'permissions' => array('user_relationships', 'friends_relationships'),
+            'description' => t("Provides access to the user's family and personal relationships and relationship status"),
+          ),
+          array(
+            'label' => t('Religion and Politics'),
+            'permissions' => array('user_religion_politics', 'friends_religion_politics'),
+            'description' => t("Provides access to the user's religious and political affiliations"),
+          ),
+          array(
+            'label' => t('Status'),
+            'permissions' => array('user_status', 'friends_status'),
+            'description' => t("Provides access to the user's most recent status message"),
+          ),
+          array(
+            'label' => t('Videos'),
+            'permissions' => array('user_videos', 'friends_videos'),
+            'description' => t("Provides access to the videos the user has uploaded"),
+          ),
+          array(
+            'label' => t('Web site'),
+            'permissions' => array('user_website', 'friends_website'),
+            'description' => t("Provides access to the user's web site URL"),
+          ),
+          array(
+            'label' => t('Work history'),
+            'permissions' => array('user_work_history', 'friends_work_history'),
+            'description' => t("Provides access to work history as the work property"),
+          ),
+          array(
+            'label' => t('Read friendlists'),
+            'permissions' => array('read_friendlists'),
+            'description' => t("Provides read access to any friend lists the user created. A user's friends are provided as part of basic data."),
+          ),
+          array(
+            'label' => t('Read requests'),
+            'permissions' => array('read_requests'),
+            'description' => t("Provides read access to the user's friend requests"),
+          ),
+        ),
+      );
+  }
+  return $perms;
+}
Index: contrib/fb_permission.css
===================================================================
RCS file: contrib/fb_permission.css
diff -N contrib/fb_permission.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ contrib/fb_permission.css	7 Aug 2010 09:24:51 -0000
@@ -0,0 +1,29 @@
+tr.fb-permissions-label td .form-item,
+tr.fb-permissions-permission td .form-item,
+tr.fb-permissions-group td .form-item {
+	white-space: normal;
+}
+
+tr.fb-permissions-group td {
+  background-color:#D8DAF5;
+  font-weight: bold;
+  margin-top:  5px;
+  margin-bottom:  5px;
+}
+
+tr.fb-permissions-label td {
+	font-weight: bold;
+}
+
+tr.fb-permissions-label td {
+  padding-left: 10px;
+  background-color:#D4E7F3;
+}
+
+tr.fb-permissions-label td .description{
+	font-weight: normal;
+}
+
+tr.fb-permissions-permission td {
+  padding-left: 20px;
+}
Index: contrib/fb_permission.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/contrib/fb_permission.module,v
retrieving revision 1.13
diff -u -p -r1.13 fb_permission.module
--- contrib/fb_permission.module	9 Jul 2010 19:54:59 -0000	1.13
+++ contrib/fb_permission.module	7 Aug 2010 09:24:51 -0000
@@ -1,7 +1,7 @@
 <?php
 /**
  * @file
- * Code pertaining to Facebook's extended permissions.  
+ * Code pertaining to Facebook's extended permissions.
  * see http://wiki.developers.facebook.com/index.php/Extended_permissions
  */
 
@@ -10,6 +10,17 @@ function fb_permission_perm() {
 }
 
 /**
+ * Implementation of hook_theme().
+ */
+function fb_permission_theme() {
+  return array(
+    'fb_permissions_map' => array(
+      'arguments' => array('elements' => NULL),
+    ),
+  );
+}
+
+/**
  * Helper function for menu item access check.
  */
 function fb_permission_access_own($account, $perm) {
@@ -18,29 +29,158 @@ function fb_permission_access_own($accou
 }
 
 /**
- * Which permissions can we prompt for?
  *
- * @TODO - update this list and/or make it customizable.
+ * 	Add extended permission structure to form
  */
-function fb_permission_map() {
-  static $perms;
-  if (!isset($perms)) {
-    // http://wiki.developers.facebook.com/index.php/Extended_permissions
-    $perms = array(
-      'email' => 'Allow %application to send you email', 
-      'offline_access' => 'Grant %application access to your Facebook profile.',
-      'status_update' => 'Allow %application to set your status.', 
-      'photo_upload' => 'Allow %application to upload photos.',
-      'user_photos' => 'Allow %application to view photos.',
-      'create_listing' => 'Allow %application to create marketplace listings on your behalf.',
-      'create_event' => 'Allow %application to create events on your behalf.',
-      'rsvp_event' => 'Allow %application to RSVP to events on your behalf',
-      'sms' => 'Allow %application to send you SMS text messages.',
-      'read_stream' => 'Allow %application to display your stream.',
-      'publish_stream' => 'Allow %application to publish to your stream.',
+function fb_permissions_map(&$form) {
+  $fb_app_data = fb_get_app_data($form['#fb_app']);
+
+  $fb_permission_data = $fb_app_data['fb_permission'];
+
+  module_load_include('inc', 'fb_permission', 'fb_permission.all_permissions');
+  $permissions_map = fb_permission_list_all_permissions();
+
+  $permission_groups = array(
+    'publishing' => t('Publishing'),
+    'page' => t('Page'),
+    'data' => t('Data'),
+  );
+
+  $form['fb_app_data']['fb_permission'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Facebook Extended Permissions'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+    '#theme' => 'fb_permissions_map',
+    '#tree' => TRUE,
+  );
+
+  //foreach permission group
+  foreach ($permission_groups as $key => $group_label) {
+    $form['fb_app_data']['fb_permission']['labels'][] = array(
+      '#type' => 'item',
+      '#value' => $group_label,
+      '#attributes' => array('class' => 'fb-permissions-group'),
     );
+
+    //foreach permission_struct in permission_group
+    foreach ($permissions_map[$key] as $permission_struct) {
+      $form['fb_app_data']['fb_permission']['labels'][] = array(
+        '#type' => 'item',
+        '#value' => $permission_struct['label'],
+        '#description' => $permission_struct['description'],
+        '#attributes' => array('class' => 'fb-permissions-label'),
+    );
+
+      //foreach permission in permission_struct
+      foreach ($permission_struct['permissions'] as $permission) {
+        //Label for applications
+        $form['fb_app_data']['fb_permission']['labels'][] = array(
+            '#value' => $permission,
+            '#attributes' => array('class' => 'fb-permissions-permission'),
+          );
+
+        //For new values
+        if (isset($fb_permission_data['map'][$permission])) {
+          $permission_default_value = $fb_permission_data['map'][$permission];
+        }
+        else{
+          $permission_default_value = 0;
+        }
+
+        //Map permission (for application)
+        $form['fb_app_data']['fb_permission']['map'][$permission] = array(
+            '#type' => 'checkbox',
+            '#default_value' => $permission_default_value,
+            '#return_value' => $permission,
+          );
+
+        //Propmpt permission (for users)
+        $form['fb_app_data']['fb_permission']['prompt'][$permission] = array(
+            '#type' => 'checkbox',
+            '#default_value' => $permission_default_value,
+            '#return_value' => $permission,
+          );
+      }
+    }
+  }
+}
+
+/**
+ * Theme the administer facebook permissions form.
+ *
+ * @ingroup themeable
+ */
+function theme_fb_permissions_map($form) {
+  //Atach CSS
+  drupal_add_css(drupal_get_path('module', 'fb_permission') . '/fb_permission.css');
+
+  //Declare header
+  $header = array(
+    '',
+    array(
+      'data'  => t('Extended Permissions'),
+      'class' => checkbox,
+    ),
+    array(
+    'data'  => t('Prompt New Users for Permission'),
+    'class' => checkbox,
+    ),
+  );
+
+  $rows = array();
+
+  //For each element children (without #) render table row
+  foreach (element_children($form['labels']) as $key) {
+    $element = $form['labels'][$key];
+    if (!isset($form['map'][$element['#value']])) {
+      $rows[] = array(
+        'data' => array(
+          array(
+            'data' => drupal_render($element),
+            'colspan' => 3,
+          )
+        ),
+        'class' => $element['#attributes']['class'],
+      );
+    }
+    else{
+      $rows[] = array(
+        'data' => array(
+          $element['#value'],
+          array(
+            'data'  => drupal_render($form['map'][$element['#value']]),
+            'class' => checkbox,
+          ),
+          array(
+            'data'  => drupal_render($form['prompt'][$element['#value']]),
+            'class' => checkbox,
+          ),
+        ),
+        'class' => $element['#attributes']['class'],
+      );
+    }
+  }
+
+  //Render table
+  $content = theme('table', $header, $rows);
+
+  return $content;
+}
+/* Get descriptions for selected permissions */
+function fb_permission_descriptions($permissions, $array_list, &$descriptions) {
+  if (isset($array_list['description'])) {
+    foreach ($permissions as $permission) {
+      if (!empty($permission) && in_array($permission, $array_list['permissions'])) {
+        $descriptions[$permission] = $array_list['description'];
+      }
+    }
+  }
+  else{
+    foreach ($array_list as $array) {
+      fb_permission_descriptions($permissions, $array, $descriptions);
+    }
   }
-  return $perms;
 }
 
 /**
@@ -53,15 +193,17 @@ function fb_permission_fb_required_perms
   $fb_app_data = fb_get_app_data($_fb_app);
   $fb_permission_data = $fb_app_data['fb_permission'];
 
-  foreach ($fb_permission_data['prompt'] as $key => $value) {
-    if ($value) {
-      $perms[$key] = $key;
+  if (!empty($fb_permission_data['prompt'])) {
+    foreach ($fb_permission_data['prompt'] as $key => $value) {
+      if ($value) {
+        $perms[$key] = $key;
+      }
     }
   }
 }
 
 /**
- * Implementation of hook_user.
+ * Implementation of hook_user().
  */
 function fb_permission_user($op, &$edit, &$account, $category = NULL) {
   global $user;
@@ -82,30 +224,26 @@ function fb_permission_user($op, &$edit,
   elseif ($op == 'form') {
     // See if the category corresponds to a facebook app.
     $fb_app = fb_get_app(array('label' => $category));
-    
+
     if ($fb_app) {
       $fb = fb_api_init($fb_app);
-      $map = fb_permission_map(); // All known permissions.
-      // Show only permissions we've configured for this app.
       $fb_app_data = fb_get_app_data($fb_app);
-      $fb_permission_data = $fb_app_data['fb_permission'];
-      if (is_array($fb_permission_data['map'])) {
-        foreach ($fb_permission_data['map'] as $key => $value) {
-          if (!$value)
-            unset($map[$key]);
-        }
-      }
+      $map = array();
+
+      module_load_include('inc', 'fb_permission', 'fb_permission.all_permissions');
+      // Show only permissions we've configured for this app.
+      fb_permission_descriptions($fb_app_data['fb_permission']['map'], fb_permission_list_all_permissions(), $map);
+
 
       /* Should not be necessary to wrap in serverfbml, as prompt-permission is documented as XFBML.
-      $form = array(
-        'perms' => array(
-          '#prefix' => '<fb:serverfbml><script type="text/fbml><fb:fbml>',
-          '#suffix' => '</fb:fbml></script></fb:serverfbml>',
-        ),
-      );
+         $form = array(
+         'perms' => array(
+         '#prefix' => '<fb:serverfbml><script type="text/fbml><fb:fbml>',
+         '#suffix' => '</fb:fbml></script></fb:serverfbml>',
+         ),
+         );
       */
-      
-      $t_args = array('%application' => $fb_app->title);
+
       $weight = 0;
       foreach ($map as $key => $text) {
         $has_perm = FALSE;
@@ -113,7 +251,7 @@ function fb_permission_user($op, &$edit,
           $has_perm = fb_call_method($fb, 'users.hasAppPermission', array(
                                        'ext_perm' => $key,
                                        'uid' => fb_get_fbu($account->uid, $fb_app),
-                                     ));
+                                      ));
         } catch (Exception $e) {
           fb_log_exception($e, t('Call to users.hasAppPermission(%key) failed.', array('%key' => $key)));
         }
@@ -122,7 +260,7 @@ function fb_permission_user($op, &$edit,
             // Ideally, fb:prompt-permission would work.  But it doesn't.
             $form['perms'][$key] = array(
               '#type' => 'markup',
-              '#value' => '<fb:prompt-permission perms="' . $key . '">' . t($text, $t_args) . '</fb:prompt-permission>',
+              '#value' => '<fb:prompt-permission perms="' . $key . '">' . $text . '</fb:prompt-permission>',
               '#weight' => $weight++,
               '#suffix' => "<br/>\n",
             );
@@ -133,7 +271,7 @@ function fb_permission_user($op, &$edit,
             $url = url($_GET['q'], array('absolute' => TRUE));
             $form['perms'][$key] = array(
               '#type' => 'markup',
-              '#value' => l(t($text, $t_args), "http://www.facebook.com/authorize.php", array(
+              '#value' => l($text, "http://www.facebook.com/authorize.php", array(
                               'html' => TRUE,
                               'query' => "api_key={$fb_app->apikey}&v=1.0&ext_perm={$key}&next={$url}&next_cancel={$url}",
                             )),
@@ -158,9 +296,7 @@ function fb_permission_user($op, &$edit,
                                       '#value' => TRUE);
       return $form;
     }
-    
   }
-  
 }
 
 function fb_permission_form_alter(&$form, $state, $id) {
@@ -169,48 +305,11 @@ function fb_permission_form_alter(&$form
     unset($form['submit']);
     unset($form['delete']);
   }
-  
+
   // Add settings to fb_app form
   if (isset($form['fb_app_data'])) {
-    $fb_app = $form['#fb_app'];
-    $fb_app_data = fb_get_app_data($fb_app);
-    $fb_permission_data = $fb_app_data['fb_permission'];
-    $form['fb_app_data']['fb_permission'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('Facebook Extended Permissions'),
-      '#tree' => TRUE,
-      '#collapsible' => TRUE,
-      '#collapsed' => TRUE,
-    );
-
-    foreach (fb_permission_map() as $key => $desc) {
-      $options[$key] = $key;
-    }
-
-    // defaults
-    if (!isset($fb_permission_data['map'])) {
-      $fb_permission_data['map'] = array();
-    }
-
-    $form['fb_app_data']['fb_permission']['map'] = array(
-      '#type' => 'checkboxes',
-      '#title' => t('Extended Permissions'),
-      '#options' => $options,
-      '#default_value' => $fb_permission_data['map'],
-      '#description' => t('Which extended permissions does this application use?  Users will be able to grant these permissions on their user edit pages.'),
-    );
-
-    if (!isset($fb_permission_data['prompt'])) {
-      $fb_permission_data['prompt'] = array();
-    }
-    $form['fb_app_data']['fb_permission']['prompt'] = array(
-      '#type' => 'checkboxes',
-      '#title' => t('Prompt New Users for Permission'),
-      '#options' => $options,
-      '#default_value' => $fb_permission_data['prompt'],
-      '#description' => t('Prompt users when they first authorize the application.  Select only the most important features.'),
-    );
-    
+    //Defaults
+    fb_permissions_map($form);
   }
 }
 
@@ -230,7 +329,7 @@ function fb_permission_fb($op, $data, &$
       $fb_app = isset($data['fb_app']) ? $data['fb_app'] : NULL;
       $fb_app_data = fb_get_app_data($fb_app);
       $fb_permission_data = $fb_app_data['fb_permission'];
-      
+
       if (is_array($fb_permission_data['prompt'])) {
         $perms = array();
         foreach ($fb_permission_data['prompt'] as $key => $value) {
