--- salesforce_api.new.module	2009-05-29 19:00:11.000000000 -0400
+++ salesforce_api.module	2009-05-30 02:05:41.000000000 -0400
@@ -19,8 +19,9 @@ define('SALESFORCE_DIR_WSDL', SALESFORCE
 
 // Define Drupal paths for various parts of the Salesforce UI.
 define('SALESFORCE_PATH_ADMIN', 'admin/settings/salesforce');
-define('SALESFORCE_PATH_FIELDMAPS', 'admin/settings/salesforce/fieldmap');
-define('SALESFORCE_PATH_DEMO', 'admin/settings/salesforce/demo');
+define('SALESFORCE_PATH_FIELDMAPS', SALESFORCE_PATH_ADMIN.'/fieldmap');
+define('SALESFORCE_PATH_DEMO', SALESFORCE_PATH_ADMIN.'/demo');
+define('SALESFORCE_PATH_OBJECT', SALESFORCE_PATH_ADMIN.'/object');
 
 // Define field importing requirements.
 // TODO: I believe we need to use bitwise operators instead.
@@ -111,6 +112,25 @@ function salesforce_api_menu() {
     'type' => MENU_CALLBACK,
     'file' => 'salesforce_api.admin.inc',
   );
+  $items[SALESFORCE_PATH_OBJECT] = array(
+    'title' => 'Object setup',
+    'description' => 'Define which SalesForce objects you would like to be available in your Drupal site.',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('salesforce_api_admin_object'),
+    'access arguments' => array('administer salesforce'),
+    'type' => MENU_LOCAL_TASK,
+    'file' => 'salesforce_api.admin.inc',
+    );
+  
+  $items[SALESFORCE_PATH_OBJECT.'/%'] = array(
+    'title' => 'Object setup',
+    'page callbacck' => 'drupal_get_form',
+    'page arguments' => array('salesforce_api_admin_object_settings', 
+                              count(explode('/', SALESFORCE_PATH_OBJECT))),
+    'access arguments' => array('administer salesforce'),
+    'type' => MENU_CALLBACK,
+    'file' => 'salesforce_api.admin.inc',
+    );
 
   return $items;
 }
@@ -592,3 +612,110 @@ function salesforce_api_theme($existing,
     ),
   );
 }
+
+/*
+* Wrapper for SOAP SforceBaseClient::describeGlobal
+* @return an SFQueryResult object (look at ->types for an array of SF object types)
+*/
+function salesforce_api_describeGlobal() {
+ static $objects;
+ if (!empty($objects)) {
+   return $objects;
+ }
+ ob_start('salesforce_api_soapfault_handler');
+$sf = salesforce_api_connect();
+if ($sf === FALSE) {
+	$link = l('Please verify that you have completed your SalesForce credentials', SALESFORCE_PATH_ADMIN);
+	drupal_set_message(t('Unable to connect to SalesForce. !link', array('!link' => $link)), 'error');
+   ob_end_clean();
+	return;
+}
+ $objects = $sf->client->describeGlobal();
+ ob_end_clean();
+ return $objects;
+}
+
+/**
+ * Load and return an array of all the local SF object types from the salesforce_object cache.
+ *
+ * @param array $options :
+ *  valid keys are:
+ *    boolean 'full' => if true, return fully-loaded SF types, decoded and unserialized. 
+ *      otherwise, return "name"s and "valid"s only
+ *    string 'conditions' => SQL WHERE clause to add to the query (e.g. 'valid <> 0')
+ * @return an array of SF types, indexed on type names
+**/
+function salesforce_api_get_types($options = array()) {
+  $options = array_merge(array(
+    'full' => TRUE,
+    'conditions' => NULL,
+    ), $options);
+  $fields = $options['full'] ? '*' : 'name, valid';
+  $where = $options['conditions'] ? 'WHERE ' . $options['conditions'] : null;
+  $sql = "SELECT $fields FROM {salesforce_objects} $where";
+  $result = db_query($sql);
+  $types = array();
+  while($row = db_fetch_array($result)) {
+    if(isset($row['cache'])) {
+      $row['cache'] = unserialize(base64_decode($row['cache']));
+    }
+    $types[$row['name']] = $row;
+  }
+  return $types;
+}
+
+/**
+ * Wrapper for SOAP SforceBaseClient::describeSObjects
+ * Given an array of sf object type, return an array of SF object definitions
+ * @param array types : an array of machine-readable names of the SF object types
+**/
+function salesforce_api_describeSObjects($types) {
+  static $objects;
+  if(is_string($types)) {
+    $types = array($types);
+  }
+  if(!is_array($types)) {
+    drupal_set_message(t('DescribeSObjects expects an array. ' . gettype($types) . ' received.'), 'error');
+    return false;
+  }
+  
+  //if we've already got everything cached, return the cached versions
+  if(!empty($objects)) {
+    $outstanding = array_diff($types, array_keys($objects));
+    if(empty($outstanding)) {
+      $ret = array();
+      foreach ($types as $k) {
+        $ret[$k] = $cache[$k];
+      }
+      return $ret;
+    }
+  }
+  
+  if (is_string($types)) {
+    $types = array($types);
+  }
+
+  ob_start('salesforce_api_soapfault_handler');
+	$sf = salesforce_api_connect();
+	if ($sf === FALSE) { 
+		$link = l('Please verify that you have completed your SalesForce credentials', SALESFORCE_PATH_ADMIN);
+		drupal_set_message(t('Unable to connect to SalesForce. !link', array('!link' => $link)), 'error');
+    ob_end_clean();
+		return;
+	}
+  $objects = $sf->client->describeSObjects($types);
+  ob_end_clean();
+  
+  if(empty($objects)) {
+    return array();
+  }
+  if (is_object($objects)) {
+    $objects = array($objects);
+  }
+  $tmp = array();
+  foreach ($objects as $o) {
+    $tmp[$o->name] = $o;
+  }
+  $objects = $tmp;
+  return $objects;
+}
\ No newline at end of file
