--- /home/xen/tmp/test/sites/all/modules/flexifield/flexifield-widget.inc	2010-11-22 15:03:09.588819508 +0100
+++ flexifield-widget.inc	2010-11-22 14:40:44.740818071 +0100
@@ -8,7 +8,7 @@
  */
 
 /**
- * Process the fieldset that contains the child fields. 
+ * Process the fieldset that contains the child fields.
  */
 function flexifield_fieldset_process($aElement, $aSubmittedElementData, $aFormState, $aForm) {
   // Ensure we have a valid content type with valid type information
@@ -16,7 +16,7 @@ function flexifield_fieldset_process($aE
   if (!$sContentType) {return $aElement;}
   $aContentTypeInfo = content_types($sContentType);
   if (!$aContentTypeInfo) {return $aElement;}
-  
+
   // For each field in that content type, add its widget form as a child of this element
   if (!isset($aForm['#node'])) {
     $aForm['#node'] = new stdClass();
@@ -35,23 +35,54 @@ function flexifield_fieldset_process($aE
     }
   }
   drupal_alter('flexifield_child_fields_form', $aElement, $aForm, $aFormState);
-  
+
   // Hack for having $aForm['#field_info'] be what it needs to be inside each of
   // the widgets' #process functions.
   _flexifield_setup_form_field_info_hack($aElement, $aContentTypeInfo['fields']);
-  
+
+  // Prevent empty submited sub form element to have any required elements
+  if (!empty($aSubmittedElementData)) {
+    // Construct pseudo item
+    $sItem = array(
+      'value' => $aSubmittedElementData,
+      'type' => $sContentType,
+    );
+    $sFieldSettings = $aForm['#field_info'][$aElement['#field_name']];
+    if (flexifield_content_is_empty($sItem, $sFieldSettings)) {
+      _flexifield_fieldset_clear_required($aElement);
+    }
+  }
+
   return $aElement;
 }
 
 /**
- * Setup the result of content_multiple_values_form() for both the 
+ * Clear required flag of a field and all its children
+ */
+function _flexifield_fieldset_clear_required(&$elements) {
+  // Recurse through all children.
+  foreach (element_children($elements) as $key) {
+    if (isset($elements[$key]) && $elements[$key]) {
+      _flexifield_fieldset_clear_required($elements[$key], $form_state);
+    }
+  }
+  if (isset($elements['#required']) && $elements['#required']) {
+    $elements['#required'] = FALSE;
+  }
+  if (isset($elements['#flexifield_storage']['#field_info']['required']) && $elements['#flexifield_storage']['#field_info']['required']) {
+    $elements['#flexifield_storage']['#field_info']['required'] = FALSE;
+  }
+}
+
+/**
+ * Setup the result of content_multiple_values_form() for both the
  * flexifield field and child fields to have some extra stuff happen
  * during form building (#process).
  */
 function _flexifield_alter_multiple_values_form(&$aElement, &$aForm, &$aFormState, $aField, $aItems = array()) {
   $aElement['#process'] = array_merge(array('_flexifield_alter_multiple_values_form_process'), flexifield_get_element_property($aElement, '#process', array()));
   $aElement['#field_name'] = $aField['field_name'];
-  
+
   // For the #process function to work, we need to set #input,
   // but doing so affects #value, and we want to be able to
   // clean that up.
@@ -62,26 +93,28 @@ function _flexifield_alter_multiple_valu
     $aElement['#flexifield_value_original'] = isset($aElement['#value']) ? $aElement['#value'] : null;
     if (!isset($aElement['#type'])) {
       $aElement['#type'] = 'markup';
+      // Prevent vlaidation errors
+      $aElement['#validated'] = TRUE;
     }
   }
 }
 
 /**
- * Adjust the result of content_multiple_values_form() for both the 
- * flexifield field and child fields. The problem is that 
+ * Adjust the result of content_multiple_values_form() for both the
+ * flexifield field and child fields. The problem is that
  * content_multiple_values_form() sets tabledrag and AHAH up with
  * assumptions that aren't true when nesting fields within flexifield.
  */
 function _flexifield_alter_multiple_values_form_process($aElement) {
   // Solve tabledrag issues by using our version of the theme hook.
   $aElement['#theme'] = 'flexifield_multiple_values';
-    
+
   // Clean up what was done by forcing #input in order to have this function run.
   if ($aElement['#flexifield_forced_input']) {
     $aElement['#input'] = $aElement['#flexifield_input_original'];
     $aElement['#value'] = $aElement['#flexifield_value_original'];
   }
-  
+
   // Solve AHAH.
   $sId = $aElement['#id'];
   $sKeyAddMore = $aElement['#field_name'] . '_add_more';
@@ -96,14 +129,14 @@ function _flexifield_alter_multiple_valu
 
 /**
  * Hack to deal with CCK widget elements using the top level form's #field_info
- * property for accessing their field information. 
+ * property for accessing their field information.
  *
  * Using the top level form's #field_info property assumes there's only
- * one field of a given field name for the entire form, and this isn't 
+ * one field of a given field name for the entire form, and this isn't
  * necessarily true for fields inside of flexifield. So, what we do
  * here is place the #field_info information on the element, and insert
  * a #process function to copy this information to the top-level form
- * before the element's normal #process function that will need this 
+ * before the element's normal #process function that will need this
  * info. We also add a final #process function to restore the top-level
  * form's #field_info to its original.
  *
@@ -114,8 +147,8 @@ function _flexifield_alter_multiple_valu
 function _flexifield_setup_form_field_info_hack(&$aElement, &$aFieldsInfo) {
   foreach (element_children($aElement) as $sKey) {
     if (
-      isset($aElement[$sKey]['#field_name']) && 
-      isset($aFieldsInfo[$aElement[$sKey]['#field_name']]) && 
+      isset($aElement[$sKey]['#field_name']) &&
+      isset($aFieldsInfo[$aElement[$sKey]['#field_name']]) &&
       !isset($aElement[$sKey]['#flexifield_storage']['#field_info'])
     ) {
       $aProcess = flexifield_get_element_property($aElement[$sKey], '#process');
@@ -158,9 +191,9 @@ function _flexifield_setup_form_field_in
  * Process function that runs after the element's "real" process function.
  * It restores the top-level form's #field_info property.
  *
- * Technically, we don't need to do this, because form.inc's 
+ * Technically, we don't need to do this, because form.inc's
  * _form_builder_handle_input_element() function takes $aForm by value instead
- * of by reference, so any changes made to it are temporary anyway. However, 
+ * of by reference, so any changes made to it are temporary anyway. However,
  * this might change in the future, so let's explicitly clean up after ourselves.
  */
 function _flexifield_restore_form_field_info($aElement, $aSubmittedElementData, $aFormState, &$aForm) {
@@ -188,7 +221,7 @@ function theme_flexifield_fieldset($aEle
   if (!isset($aElement['#children'])) {
     $aElement['#children'] = NULL;
   }
-  
+
   // We setup the ahah code on the item type selector to target the element id
   // that is created by theme('form_element'). Therefore, we do not want to
   // create this element when re-rendering from the ahah callback.
@@ -214,21 +247,21 @@ function flexifield_ahah_changetype($sEl
     drupal_json(array('data' => ''));
     exit;
   }
-  
+
   // Build the form, so that we can render the element we want.
   // It seems like overkill to build the entire form, when we just
   // want one field item from it. Perhaps this can be optimized.
   $aFormCopy = $aForm;
   $aFormCopy['#post'] = $_POST;
   $aBuiltForm = form_builder($_POST['form_id'], $aFormCopy, $aFormState);
-  
+
   // Get just the element that needs re-rendering.
   $aElement = $aBuiltForm;
   foreach (explode(':', $sElementParents) as $sParent) {
     $aElement = $aElement[$sParent];
   }
   $aElement = $aElement['value'];
-  
+
   // Return the rendered element as an ahah response
   $aElement['#flexifield_from_ahah'] = TRUE;
   print theme('ahah_response', drupal_render($aElement));
@@ -239,19 +272,19 @@ function flexifield_ahah_changetype($sEl
  * Menu callback for adding another item to a multi-valued field.
  * Used for both flexifields and fields within flexifield.
  */
-function flexifield_ahah_addmore($sTypeNameUrl, $sFieldName, $sParents, $sDataParents) {  
+function flexifield_ahah_addmore($sTypeNameUrl, $sFieldName, $sParents, $sDataParents) {
   $aParents = explode(':', $sParents);
   while (array_pop($aParents) != $sFieldName) {}
   $aDataParents = explode(':', $sDataParents);
   while (array_pop($aDataParents) != $sFieldName) {}
-  
+
   // If this is the root flexifield, then use content.module's way of
   // adding another item (with a small modification).
   if (!count($aParents)) {
     module_load_include('inc', 'flexifield', 'flexifield-cck-overrides');
     return flexifield_add_more_js($sTypeNameUrl, $sFieldName);
   }
-  
+
   // Retrieve the cached form.
   $aFormState = array('submitted' => FALSE);
   $sFormBuildId = $_POST['form_build_id'];
@@ -261,7 +294,7 @@ function flexifield_ahah_addmore($sTypeN
     drupal_json(array('data' => ''));
     exit;
   }
-  
+
   // Build the form, so that we can render the element we want.
   // It seems like overkill to build the entire form, when we just
   // want one field item from it. Perhaps this can be optimized.
@@ -273,14 +306,14 @@ function flexifield_ahah_addmore($sTypeN
   }
   $aFormPostReference[$sFieldName][] = array();
   $aBuiltForm = form_builder($_POST['form_id'], $aFormCopy, $aFormState);
-  
+
   // Get just the element that needs re-rendering.
   $aElement = $aBuiltForm;
   foreach ($aParents as $sParent) {
     $aElement = $aElement[$sParent];
   }
   $aElement = $aElement[$sFieldName];
-  
+
   // Return the rendered element as an ahah response
   $sRenderedElement = drupal_render($aElement);
   print theme('ahah_response', $sRenderedElement);
