Index: includes/groupcontent.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/og/includes/groupcontent.inc,v
retrieving revision 1.6
diff -u -r1.6 groupcontent.inc
--- includes/groupcontent.inc	23 Mar 2008 12:01:31 -0000	1.6
+++ includes/groupcontent.inc	26 Mar 2008 01:22:34 -0000
@@ -1,55 +1,143 @@
 <?php
+// $Id$
 
-function og_panels_ct_list_mission() {
-  $items['og_mission'] = array(
-    'title' => t('Welcome message'),
+/**
+ * @file contexts/groupcontent.inc
+ *
+ * Panels plugin to provide og-specific content types
+ */
+
+/**
+ * Return all available og content types and their panels selection menu parameters
+ *
+ */
+function og_panels_contenttype_list() {
+  $defaults = array(
     'icon' => 'user-multiple.png',
-    'path' => drupal_get_path('module', 'og_panels'). '/',
-    'description' => t('The welcome message for the group. Specified on group edit form'),
+    'path' => drupal_get_path('module', 'og_panels'). '/', // TODO why?
     'required context' => new panels_required_context(t('Group'), 'group'),
-    'category' => array(t('Organic groups'), -10),
-    
+    'category' => array(t('Organic groups'), -5),
   );
-  return $items;
+  $types = og_panels_contenttype_helper_list(TRUE);
+  foreach (array_keys($types) as $ct) {
+    $types[$ct] += $defaults;
+  }
+  return $types;
 }
 
-function og_panels_ct_list_description() {
-  $items['og_description'] = array(
-    'title' => t('Group description'),
-    'icon' => 'user-multiple.png',
-    'path' => drupal_get_path('module', 'og_panels'). '/',
-    'description' => t('The group description as specified on the group edit form.'),
-    'required context' => new panels_required_context(t('Group'), 'group'),
-    'category' => array(t('Organic groups'), -5),
+/**
+ * Return an array with data on each defined group content type
+ *
+ * @param bool $listonly
+ *  If TRUE, returns only the values required for defining the content type
+ * @return array $ctlist
+ */
+function og_panels_contenttype_helper_list($listonly = FALSE) {
+  $ctlist = array(
+    'og_mission' => array(
+      'title' => t('Welcome Message'),
+      'description' => t('The welcome message for the group. Specified on the group edit form.')),
+    'og_description' => array(
+      'title' => t('Group Description'),
+      'description' => t('The group description as specified on the group edit form.')),
+    'og_subscribers' => array(
+      'title' => t('Group Members'),
+      'description' => t('A configurable list of group members.')),
   );
-  return $items;
-}
 
-function og_panels_ct_list_subscribers() {
-  $items['og_subscribers'] = array(
-    'title' => t('Group Subscribers'),
-    'icon' => 'user-multiple.png',
-    'path' => drupal_get_path('module', 'og_panels'). '/',
-    'description' => t('The list of group subscribers or just group admins.'),
-    'required context' => new panels_required_context(t('Group'), 'group'),
-    'category' => array(t('Organic groups'), -5),
+  $ctextra = array(
+    'og_mission' => array(  
+      'subject' => t('Welcome'),
+      'contextfail' => t('Welcome statement goes here.')),
+    'og_description' => array(
+      'subject' => t('Description'),
+      'contextfail' => t('Description goes here.')),
+    'og_subscribers' => array(
+      'subject' => t('Group Members'),
+      'contextfail' => t('Members list goes here.')),
   );
-  return $items;
+  
+  if ($search = module_exists('search')) {
+    $ctlist['og_search'] = array(
+      'title' => t('Group Search'),
+      'description' => t('Search this group.'),
+    );
+    $ctextra['og_search'] = array(
+      'subject' => t('Search'),
+      'contextfail' => t('Search form goes here.'),    
+    );
+  }  
+  if (!$listonly) {
+    foreach ($ctextra as $ct => $settings) {
+      $ctlist[$ct] = array_merge($ctlist[$ct], $settings);
+    }
+  }
+  return $ctlist;
 }
 
-function og_panels_ct_list_search() {
-  $items['og_search'] = array(
-    'title' => t('Group search'),
-    'icon' => 'user-multiple.png',
-    'path' => drupal_get_path('module', 'og_panels'). '/',
-    'description' => t('Search this group.'),
-    'required context' => new panels_required_context(t('Group'), 'group'),
-    'category' => array(t('Organic groups'), -5),
+/**
+ * Return the form creating a new pane from a group content type
+ *
+ * @param string $id
+ *   the internal system name of the group ct being added
+ * @param string $parents // @TODO yeah yeah
+ * @param array $conf
+ * @return $form
+ */
+function og_panels_contenttype_add($id, $parents, $conf = NULL) {
+  return og_panels_contenttype_edit($id, $parents, $conf);
+}
+
+function og_panels_contenttype_edit($id, $parents, $conf) {
+  // allow content types to add their own individualized options to the configuration form
+  $function = 'og_panels_contenttype_helper_edit_'. substr($id, 3); // gets rid of 'og_' prefix, just to save a little redundancy in function names
+  if (function_exists($function)) {
+    $form = $function($id, $parents, $conf);
+  }
+
+  $form['og_panels_ct'] = array(
+    '#type' => 'value',
+    '#value' => $id,
+  );
+  $form['og_visibility'] = array(
+    '#type' => 'radios',
+    '#title' => t('Who should be able to view this pane?'),
+    '#required' => TRUE,
+    '#options' => array('all' => 'Everyone', 'nonmember' => 'Only Non-Members', 'member' => 'Only Group Members', 'admin' => 'Only Group Administrators'),
+    '#default_value' => isset($conf['og_visibility']) ? $conf['og_visibility'] : 'all',
   );
-  return $items;
+  
+  if (!user_access('advanced og panels editing')) { // @TODO implement API in panels to accomodate this. need to take multiple actions based on values that are passed in 
+    $form['unsets'] = array('override_title', 'css');
+  }
+  return $form;
+}
+
+function og_panels_contenttype_title($conf) {
+  $ctlist = og_panels_contenttype_helper_list();
+  return $ctlist[$conf['og_panels_ct']]['subject'];
+}
+
+// No need for a submit function at this time
+/*function og_panels_contenttype_submit(&$form_values) {
+  
 }
+*/
 
-function og_panels_ct_render_callback_mission($conf, $panel_args, $context) {
+/**
+ * Handle og_panels content types validation requests.
+ * 
+ * @TODO could this goal be more effectively reached through judicious use of the fapi and #base?
+ */
+function og_panels_contenttype_validate($form) {
+  global $form_values;
+  $function = 'og_panels_contenttype_helper_validate_'. substr($form_values['og_panels_ct'], 3);
+  if (function_exists($function)) {
+    call_user_func_array($function, array($form_values, $form));
+  }
+}
+
+function og_panels_contenttype_render_callback_mission($conf, $panel_args, $context) {
   $node = isset($context->data) ? drupal_clone($context->data) : NULL;
   $block->module = 'og_panels';
 
@@ -71,64 +159,62 @@
     $block->content = t('Welcome statement goes here.');
     $block->delta = 'unknown';
   }
-
-  return $block;
 }
 
-function og_panels_ct_render_callback_description($conf, $panel_args, $context) {
-  $node = isset($context->data) ? drupal_clone($context->data) : NULL;
+/**
+ * Render an og_panel pane
+ *
+ * @param array $conf
+ *   An associative array containing saved pane configuration data from the database
+ * @param unknown_type $panel_args
+ * @param object $context
+ *   A panels context object containing group context data
+ */
+function og_panels_contenttype_render($conf, $panel_args, $context) {
   $block->module = 'og_panels';
-
-  $block->subject = t('Description');
-  if ($node) {
-    $block->content = check_markup($node->og_description);
-    $block->delta = $node->nid;
-  }
-  else {
-    $block->content = t('Description goes here.');
+  $ctlist = og_panels_contenttype_helper_list();
+  $block->subject = $ctlist[$conf['og_panels_ct']]['subject'];
+  if (!isset($context->data)) {
+    $block->content = $ctlist[$conf['og_panels_ct']]['contextfail'];
     $block->delta = 'unknown';
+    return $block;
   }
-
-  return $block;
-}
-
-function og_panels_ct_render_callback_subscribers($conf, $panel_args, $context) {
-  $node = isset($context->data) ? drupal_clone($context->data) : NULL;
-  $block->module = 'og_panels';
-
-  $block->subject = t('Group Members');
-  if ($node) {
-    $block->content = og_block_subscribers_list($node->nid, $conf['num_items'], $conf['og_panels_subscribers_is_admin'], $conf['show_more'], $conf['show_picture']);
+  if ($visible = og_panels_contenttype_helper_visibility($conf['og_visibility'], $context->data->nid)) {
+    $node = drupal_clone($context->data);
     $block->delta = $node->nid;
+    $function = 'og_panels_contenttype_helper_render_'. substr($conf['og_panels_ct'], 3); // this function should always exist. if it doesn't, something's wrong/broken.
+    $block->content = call_user_func_array($function, array($conf, $panels_args, $context, $node));
+    return $block;
   }
-  else {
-    $block->content = t('Member list goes here.');
-    $block->delta = 'unknown';
-  }
+}
 
-  return $block;
+function og_panels_contenttype_helper_render_mission($conf, $panel_args, $context, $node) {
+  // This rendering somewhat verbose technique exactly matches og_view_group().
+  $value = check_markup($node->body, $node->format, FALSE);
+  $form['og_mission'] = array(
+    '#theme' => 'og_mission', 
+    '#value' => $value,
+    '#node' => $node,
+    '#weight' => -3,
+  );
+  return drupal_render($form['og_mission']);
 }
 
-function og_panels_ct_render_callback_search($conf, $panel_args, $context) {
-  $node = isset($context->data) ? drupal_clone($context->data) : NULL;
-  $block->module = 'og_panels';
+function og_panels_contenttype_helper_render_description($conf, $panel_args, $context, $node) {
+  return check_markup($node->og_description);
+}
 
-  $block->subject = t('Group Search');
-  if ($node) {
-    if (module_exists('search') && user_access('search content')) {
-      $block->content = drupal_get_form('og_search_form', $node);
-    }
-    $block->delta = $node->nid;
-  }
-  else {
-    $block->content = t('Search form goes here.');
-    $block->delta = 'unknown';
-  }
+function og_panels_contenttype_helper_render_subscribers($conf, $panel_args, $context, $node) {
+  return og_block_subscribers_list($node->nid, $conf['num_items'], $conf['og_panels_subscribers_is_admin'], $conf['show_more'], $conf['show_picture']);
+}
 
-  return $block;
+function og_panels_contenttype_helper_render_search($conf, $panel_args, $context, $node) {
+  if (user_access('search content')) {
+    return drupal_get_form('og_search_form', $node);
+  }
 }
 
-function og_panels_content_types_addedit_callback_subscribers($id, $panel_args, $conf = NULL) {
+function og_panels_contenttype_helper_edit_subscribers($id, $panel_args, $conf = NULL) {
   $form['num_items'] = array(
     '#type' => 'textfield',
     '#title' => t('Number of members'),
@@ -158,7 +244,7 @@
   return $form;
 }
 
-function og_panels_content_types_validate_callback_subscribers($form, $form_values) {
+function og_panels_contenttype_helper_validate_subscribers($form_values, $form) {
   if (!is_numeric($form_values['num_items'])) {
     form_error($form['num_items'], t('Number of members must be an integer.'));
   }
@@ -166,19 +252,35 @@
   form_set_value($form['og_panels_subscribers_is_admin'], array_filter($form_values['og_panels_subscribers_is_admin']));
 }
 
-function og_panels_ct_title_callback_mission($conf, $context) {
-  return t('Welcome');
-}
-
-function og_panels_ct_title_callback_description($conf, $context) {
-  return t('Description');
-}
-
-function og_panels_ct_title_callback_subscribers($conf, $context) {
-  return t('Group members');
-}
-
-function og_panels_ct_title_callback_search($conf, $context) {
-  return t('Search');
+/**
+ * Determine pane visibility based on pane settings and the user's group membership status
+ *
+ * @param string $op
+ *   Pane visibility setting
+ * @param int $nid
+ *   The nid of the group being referenced
+ * @return bool $visible
+ *   Given the parameters passed in, indicates whether or not the pane should be rendered for that user
+ */
+function og_panels_contenttype_helper_visibility($op, $nid) {
+  // use static variable to somewhat reduce queries on complex og_panels pages
+  static $visible;
+  if (!is_array($visible)) {
+    $visible = array();
+    $visible['all'] = TRUE;
+  }
+  if (!isset($visible[$op])) {
+    global $user;
+    $members = array();
+    // @TODO this query currently excludes inactive group members, effectively placing them in the 'nonmember' grouping. Should this be changed?
+    $sql = "SELECT u.uid AS uid, ogu.is_admin AS admin FROM {og_uid} ogu INNER JOIN {users} u ON ogu.uid = u.uid WHERE ogu.nid = %d AND ogu.is_active = 1 AND u.status = 1 ORDER BY ogu.created DESC";
+    $result = db_query($sql, $nid);
+    while ($account = db_fetch_array($result)) {
+      $members[$account['uid']] = $account['admin']; 
+    }
+    $visible['member'] = in_array($user->uid, array_keys($members));
+    $visible['nonmember'] = !$visible['member'];
+    $visible['admin'] = $visible['member'] ? $members[$user->uid] : FALSE;
+  }
+  return $visible[$op];
 }
-
Index: og_panels.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/og/og_panels.install,v
retrieving revision 1.3
diff -u -r1.3 og_panels.install
--- og_panels.install	17 Mar 2008 15:01:53 -0000	1.3
+++ og_panels.install	26 Mar 2008 01:22:34 -0000
@@ -47,6 +47,12 @@
   return $ret ? $ret : array();
 }
 
+function og_panels_update_5002() {
+  // update pane types to reflect new integrated group content structure
+  $ret[] = update_sql("UPDATE {panels_pane} SET type = 'og_panels' WHERE type IN ('og_subscribers', 'og_mission', 'og_description', 'og_search')");
+  return $ret;
+}
+
 function og_panels_uninstall() {
   db_query('DROP TABLE {og_panels}');
 
Index: og_panels.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/og/og_panels.module,v
retrieving revision 1.19
diff -u -r1.19 og_panels.module
--- og_panels.module	25 Mar 2008 18:50:18 -0000	1.19
+++ og_panels.module	26 Mar 2008 01:22:34 -0000
@@ -9,6 +9,9 @@
         return t(
           '<p>Create custom pages for your group. Use custom pages to organize your content in a pretty and informative manner. Your group can group to be a whole website within a web site. Each custom page becomes a tab when viewing your group. One of your custom pages should be designated as your <em>group home page</em>. That page will then display when visitors first arrive at your group.</p>
           <p>Start by clicking the <a href="!url">Add new page</a> tab. Then you will choose a custom layout for your page. Then you will want to <em>edit content</em> for your custom page.</p>', array('!url' => url('node/'. arg(1). '/og_panels/form')));
+      case (arg(0) == 'admin' && arg(2) == 'og_panels'):
+        $text = !is_null(arg(3)) ? 'organic groups administrators' : 'group administrators';
+        return t("Use this page to define the content that will be available to $text while editing the content of a group panel.");
   }
 }
 
@@ -19,8 +22,23 @@
       'title' => 'Organic groups panels',
       'description' => 'Configure the content that is available to group admins when creating group pages.',
       'callback' => 'og_panels_admin_content',
+      'callback arguments' => array('groupadmin'),          
       'access' => user_access('administer organic groups'),
     );
+    $items[] = array(
+      'path' => 'admin/og/og_panels/groupadmin',
+      'title' => 'Group Administrators',
+      'description' => 'Configure the content available to group admins.', 
+      'type' => MENU_DEFAULT_LOCAL_TASK,
+    );
+    $items[] = array(
+      'path' => 'admin/og/og_panels/ogadmin',
+      'title' => 'OG Administrators',
+      'description' => 'Configure the content available to OG panels admins.',
+      'callback' => 'og_panels_admin_content',
+      'callback arguments' => array('ogadmin'),
+      'type' => MENU_LOCAL_TASK,
+    );        
   }
   else {
     if (arg(0) == 'node' && is_numeric(arg(1))) {
@@ -122,7 +140,7 @@
 }
 
 function og_panels_perm() {
-  return array('manage OG panels pages');
+  return array('manage OG panels pages', 'advanced og panels editing');
 }
 
 function og_panels_delete_confirm($did, $group_node) {
@@ -401,7 +419,8 @@
     $display->context = array('og_panels' => panels_context_create('group', $group_node));
     if ($ct) {
       panels_load_include('common');
-      $display->content_types = panels_common_get_allowed_types('og_panels', $display->context);
+      $admin = user_access('advanced og panels editing') ? 'ogadmin' : 'groupadmin';
+      $display->content_types = panels_common_get_allowed_types("og_panels_$admin", $display->context);
     }
   }
   return is_object($display) ? $display : FALSE;
@@ -517,9 +536,9 @@
   print theme('page', panels_edit($display, "node/$group_node->nid/og_panels", $display->content_types), FALSE);
 }
 
-function og_panels_admin_content() {
+function og_panels_admin_content($admin) {
   panels_load_include('common');
-  return drupal_get_form('panels_common_settings', 'og_panels');
+  return drupal_get_form('panels_common_settings', "og_panels_$admin");
 }
 
 /**
@@ -545,48 +564,19 @@
  */
 function og_panels_panels_content_types() {
   include_once './'. drupal_get_path('module', 'og_panels') .'/includes/groupcontent.inc';
-  $items['og_mission'] = array(
-    'title' => t('OG mission'),
-    'content_types' => 'og_panels_ct_list_mission',
-    'single' => TRUE, // only provides a single content type
-    'render callback' => 'og_panels_ct_render_callback_mission',
-//      'add callback' => 'og_panels_content_types_add_callback',
-//      'edit callback' => 'og_panels_content_types_edit_callback',
-    'title callback' => 'og_panels_ct_title_callback_mission',
-//    'add submit callback' => 'panels_admin_submit_group',
-//    'edit submit callback' => 'panels_admin_submit_group',
-//    'validate callback' => 'panels_admin_validate_group',
-  );
-  $items['og_description'] = array(
-    'title' => t('OG description'),
-    'content_types' => 'og_panels_ct_list_description',
-    'single' => TRUE, // only provides a single content type
-    'render callback' => 'og_panels_ct_render_callback_description',
-    'title callback' => 'og_panels_ct_title_callback_description',
-  );
-  
-    $items['og_subscribers'] = array(
-      'title' => t('OG Members'),
-      'content_types' => 'og_panels_ct_list_subscribers',
-      'single' => TRUE, // only provides a single content type
-      'render callback' => 'og_panels_ct_render_callback_subscribers',
-      'add callback' => 'og_panels_content_types_addedit_callback_subscribers',
-      'edit callback' => 'og_panels_content_types_addedit_callback_subscribers',
-      'title callback' => 'og_panels_ct_title_callback_subscribers',
-      'add validate callback' => 'og_panels_content_types_validate_callback_subscribers',
-      'edit validate callback' => 'og_panels_content_types_validate_callback_subscribers',
-    );
-    
-    if (module_exists('search')) {
-      $items['og_search'] = array(
-        'title' => t('Group search'),
-        'content_types' => 'og_panels_ct_list_search',
-        'single' => TRUE, // only provides a single content type
-        'render callback' => 'og_panels_ct_render_callback_search',
-        'title callback' => 'og_panels_ct_title_callback_search',
-      );
-    }
-    
+  // submit functions are not currently needed
+  $items['og_panels'] = array(
+    'title' => t('OG Panels'), // TODO change?
+    'content_types' => 'og_panels_ct_list',
+    'render callback' => 'og_panels_ct_render',
+    'add callback' => 'og_panels_ct_add',
+    'edit callback' => 'og_panels_ct_edit',
+    'title callback' => 'og_panels_ct_title',
+    //'add submit callback' => 'og_panels_ct_submit',
+    //'edit submit callback' => 'og_panels_ct_submit',
+    'add validate callback' => 'og_panels_ct_validate',
+    'edit validate callback' => 'og_panels_ct_validate',
+  );    
   return $items;
 }
 
