--- generic_callbacks.inc.20100826	2010-08-26 12:10:06.000000000 +1000
+++ generic_callbacks.inc	2010-08-26 12:03:43.000000000 +1000
@@ -1,5 +1,5 @@
 <?php
-// $Id: generic_callbacks.inc,v 1.1 2010/02/14 02:16:12 mjd Exp $
+// $Id: generic_callbacks.inc,v 1.7 2010/07/28 04:58:44 mjd Exp $
 /**
  * @file
  * Field Tool - Generic callbacks
@@ -30,12 +30,42 @@
  */
 function fieldtool_field_generic_get($entity, $field_name, $field_info, $deltas = array()) {
   $path = _fieldtool_delta_replace($field_info['field path'], $deltas);
-
+  
+  // Turn path into full entity path
   if (is_array($entity)) {
     $path = _fieldtool_object_path_to_array($path);
-    return eval('return isset($entity'. $path .') ? $entity'. $path .' : NULL;');
+    $path = '$entity'. $path;
+  }
+  else {
+    $path = '$entity->'. $path;
+  }
+  
+  $pos = strpos($path, '[all]');
+  if ($pos !== FALSE ) {
+    $paths = array();
+    $list = substr($path, 0, $pos);
+    eval($list .' = is_array('. $list .') ? '. $list .' : array();');
+    $keys = eval('return array_keys('. $list .');');
+    foreach ($keys as $key) {
+      $paths[] = _fieldtool_field_generic_single_value_get($entity, str_replace('[all]', "[$key]", $path));
+    }
+    if (count($paths) > 1) {
+      return $paths;
+    }
+    else {
+      return $paths[0];
+    }
+  }
+  else {
+    return _fieldtool_field_generic_single_value_get($entity, $path);
   }
-  return eval('return isset($entity->'. $path .') ? $entity->'. $path .' : NULL;');
+}
+
+/**
+ * Helper function for fieldtool_field_generic_get().
+ */
+function _fieldtool_field_generic_single_value_get($entity, $path) {
+  return eval('return isset('. $path .') ? '. $path .' : NULL;');
 }
 
 /**
@@ -45,23 +75,48 @@ function fieldtool_field_generic_get($en
  */
 function fieldtool_field_generic_set(&$entity, $field_name, $value, $field_info, $deltas = array()) {
   $path = _fieldtool_delta_replace($field_info['field path'], $deltas);
+
+  // Turn path into full entity path
   if (is_array($entity)) {
     $path = _fieldtool_object_path_to_array($path);
-    if (isset($value)) {
-      eval('$entity'. $path .' = $value;');
-    }
-    else {
-      eval('unset($entity'. $path .');');
-    }
+    $path = '$entity'. $path;
   }
   else {
-    if (isset($value)) {
-      eval('$entity->'. $path .' = $value;');
-    }
-    else {
-      eval('unset($entity->'. $path .');');
+    $path = '$entity->'. $path;
+  }
+
+  if (!is_array($value)) {
+    $value = array($value);
+  }
+  
+  $pos = strpos($path, '[all]');
+  if ($pos !== FALSE ) {
+    $paths = array();
+    $list = substr($path, 0, $pos);
+    eval($list .' = is_array('. $list .') ? '. $list .' : array();');
+    $keys = eval('return array_keys('. $list .');');
+    foreach ($keys as $key) {
+      _fieldtool_field_generic_single_value_set($entity, str_replace('[all]', "[$key]", $path), $value[$key]);
+      unset($value[$key]);
+    }
+    // if there are any new values left over, add them.
+    if (count($value)) { 
+      foreach (array_keys($value) as $key) {
+        _fieldtool_field_generic_single_value_set($entity, str_replace('[all]', "[$key]", $path), $value[$key]);
+        unset($value[$key]);
+      }
     }
   }
+  else { // Assuming that you won't have passed an array here...
+    _fieldtool_field_generic_single_value_set($entity, $path, $value[0]);
+  }
+}
+
+/**
+ * Helper function for fieldtool_field_generic_set().
+ */
+function _fieldtool_field_generic_single_value_set($entity, $path, $value = NULL) {
+  eval($path .' = $value;');
 }
 
 /**
@@ -70,7 +125,46 @@ function fieldtool_field_generic_set(&$e
  * import callback.
  */
 function fieldtool_field_generic_import(&$entity, $field_name, $value, $field_info, $deltas = array()) {
-  return fieldtool_set($field_info, $entity, $value, $deltas);
+  $itemization_callback = fieldtool_get_function($field_info, 'itemization callback');
+  
+  $messages = array(
+    'error' => array(),
+    'warning' => array(),
+    'status' => array(),
+  );
+  
+  // Replace line breaks in single-line fields
+  if ($field_info['single line']) {
+    $value = str_replace("\n", ' ', $value);
+  }
+
+  if (!$itemization_callback) {
+    $value = $value;
+  }
+  else {
+    // This is a bit convoluted for backward-compatibility.
+    // In future we may require itemization callbacks return value + messages.
+    if (is_array($value)) {
+      foreach ($value as &$v) {
+        $v = $itemization_callback($field_info, $v);
+        if (is_array($v) && array_key_exists('fieldtool_itemized_value', $v)) {
+          $messages = is_array($v['messages']) ? fieldtool_message_merge($messages, $v['messages']) : $messages;
+          $v = $v['fieldtool_itemized_value'];
+        }
+      }
+    }
+    else {
+      $value = $itemization_callback($field_info, $value);
+      if (is_array($value) && array_key_exists('fieldtool_itemized_value', $value)) {
+        $messages = is_array($value['messages']) ? fieldtool_message_merge($messages, $value['messages']) : $messages;
+        $value = $value['fieldtool_itemized_value'];
+      }
+    }
+  }
+  
+  fieldtool_set($field_info, $entity, $value, $deltas);
+  
+  return $messages;
 }
 
 /**
@@ -79,7 +173,23 @@ function fieldtool_field_generic_import(
  * export callback.
  */
 function fieldtool_field_generic_export($entity, $field_name, $field_info, $deltas = array()) {
-  return fieldtool_get($field_info, $entity, $deltas);
+  $values = fieldtool_get($field_info, $entity, $deltas);
+  $extraction_callback = fieldtool_get_function($field_info, 'extraction callback');
+
+  if (!$extraction_callback) {
+    return $values;
+  }
+  else {
+    if (is_array($values)) {
+      foreach ($values as &$value) {
+        $value = $extraction_callback($field_info, $value);
+      }
+      return $values;
+    }
+    else {
+      return $extraction_callback($field_info, $values);
+    }
+  }
 }
 
 /**
@@ -87,7 +197,7 @@ function fieldtool_field_generic_export(
  * extraction callback and no child fields are assumed to want this as their
  * extraction callback.
  */
-function fieldtool_generic_value_extract($field_info, $item) {
+function fieldtool_field_generic_value_extract($field_info, $item) {
   return $item;
 }
 
@@ -102,7 +212,7 @@ function fieldtool_generic_value_extract
  * that requires a non-scalar value for the setter callback, or can reasonably 
  * expect non-scalar import data, please write your own itemization callback.
  */
-function fieldtool_generic_value_itemize($field_info, $value) {
+function fieldtool_field_generic_value_itemize($field_info, $value) {
   if (is_object($value)) {
     $value = (array) $value;
   }
@@ -119,7 +229,29 @@ function fieldtool_generic_value_itemize
     }
     
     $value = implode(', ', $value);
-  } 
+  }
+  
+  // Handle CCK allowed values
+  if (array_key_exists('cck field type', $field_info)) {
+    // Get 'root' CCK field name
+    $tmp = explode('-', $field_info['name']);
+    $cck_name = $tmp[0];
+    $cck_field = content_fields($cck_name);
+    $allowed_values = content_allowed_values($cck_field);
+    if (count($allowed_values)) {
+      if (array_key_exists($value, $allowed_values)) {  // If $value is one of the allowed value keys.
+        break;
+      }
+      else {
+        foreach ($allowed_values as $key => $allowed_value) {
+          if ($value == $allowed_value) {
+            $value = $key;
+            break;
+          }
+        }
+      }
+    }
+  }
   
   return $value;
 }
@@ -140,9 +272,12 @@ function _fieldtool_delta_replace($path,
     }
   }
   
-  // Assume that if there's a placeholder remaining on the end,
+  // Assume that if there's at least one placeholder remaining,
   // we want all values.
-  $path = preg_replace('/\[\%\]$/', '', $path);
+  $pos = strrpos($path, '[%]');
+  if ($pos !== FALSE) {
+    $path = substr_replace($path, 'all', $pos + 1, 1);
+  }
   
   // Assume for any leftover placeholders we wanted the first item
   $path = str_replace('[%]', '[0]', $path);
@@ -208,13 +343,13 @@ function fieldtool_path($entity_type, $f
   $path = array();
   while($parent = fieldtool_get_parent($entity_type, $field_info)) {
     if (!$field_info['virtual']){
-      // Strip any helpful '_%_' delta placeholders in names
-      $parent['name'] = str_replace('_%_', '_', $parent['name']);
-      $field_info['name'] = str_replace('_%_', '_', $field_info['name']);
+      // Strip any helpful '-%-' delta placeholders in names
+      $parent['name'] = str_replace('-%-', '-', $parent['name']);
+      $field_info['name'] = str_replace('-%-', '-', $field_info['name']);
       $type = is_array($parent['fields']) ? 'array' : 'object';
       $bit = array(
         'type' => $type,
-        'name' => preg_replace('/^'. $parent['name'] .'_/', '', $field_info['name']),
+        'name' => preg_replace('/^'. $parent['name'] .'-/', '', $field_info['name']),
         'multiple' => $field_info['multiple'],
       );
       array_unshift($path, $bit);
