? .cache
? .settings
Index: modules/field/field.api.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.api.php,v
retrieving revision 1.51
diff -u -p -r1.51 field.api.php
--- modules/field/field.api.php	2 Dec 2009 19:26:21 -0000	1.51
+++ modules/field/field.api.php	5 Dec 2009 19:43:58 -0000
@@ -347,10 +347,6 @@ function hook_field_sanitize($obj_type, 
  *   The type of $object.
  * @param $object
  *   The object for the operation.
- *   Note that this might not be a full-fledged 'object'. When invoked through
- *   field_attach_query(), the $object will only include properties that the
- *   Field API knows about: bundle, id, revision id, and field values (no node
- *   title, user name...).
  * @param $field
  *   The field structure for the operation.
  * @param $instance
@@ -944,11 +940,6 @@ function hook_field_attach_form($obj_typ
  * indexed by object id. For performance reasons, information for all available
  * objects should be loaded in a single query where possible.
  *
- * Note that $objects might not be full-fledged 'objects'. When invoked through
- * field_attach_query(), each object only includes properties that the Field
- * API knows about: bundle, id, revision id, and field values (no node title,
- * user name...)
-
  * The changes made to the objects' field values get cached by the field cache
  * for subsequent loads.
  *
Index: modules/field/field.attach.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.attach.inc,v
retrieving revision 1.60
diff -u -p -r1.60 field.attach.inc
--- modules/field/field.attach.inc	4 Dec 2009 16:49:46 -0000	1.60
+++ modules/field/field.attach.inc	5 Dec 2009 19:43:58 -0000
@@ -685,11 +685,16 @@ function field_attach_load_revision($obj
  *   The type of $object; e.g. 'node' or 'user'.
  * @param $object
  *   The object with fields to validate.
- * @return
- *   Throws a FieldValidationException if validation errors are found.
+ * @throws FieldValidationException
+ *   If validation errors are found, a FieldValidationException is thrown. The
+ *   'errors' property contains the array of errors, keyed by field name,
+ *   language and delta.
  */
 function field_attach_validate($obj_type, $object) {
   $errors = array();
+  // Check generic, field-type-agnostic errors first.
+  _field_invoke_default('validate', $obj_type, $object, $errors);
+  // Check field-type specific errors.
   _field_invoke('validate', $obj_type, $object, $errors);
 
   // Let other modules validate the object.
Index: modules/field/field.default.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.default.inc,v
retrieving revision 1.23
diff -u -p -r1.23 field.default.inc
--- modules/field/field.default.inc	9 Nov 2009 18:23:41 -0000	1.23
+++ modules/field/field.default.inc	5 Dec 2009 19:52:37 -0000
@@ -21,6 +21,49 @@ function field_default_extract_form_valu
   }
 }
 
+/**
+ * Generic field validation handler.
+ *
+ * Possible error codes:
+ * - 'field_cardinality': The number of values exceeds the field cardinality.
+ *
+ * @see _hook_field_validate()
+ *
+ * @param $obj_type
+ *   The type of $object.
+ * @param $object
+ *   The object for the operation.
+ * @param $field
+ *   The field structure for the operation.
+ * @param $instance
+ *   The instance structure for $field on $object's bundle.
+ * @param $langcode
+ *   The language associated to $items.
+ * @param $items
+ *   $object->{$field['field_name']}[$langcode], or an empty array if unset.
+ * @param $errors
+ *   The array of errors, keyed by field name and by value delta, that have
+ *   already been reported for the object. The function should add its errors
+ *   to this array. Each error is an associative array, with the following
+ *   keys and values:
+ *   - 'error': an error code (should be a string, prefixed with the module name)
+ *   - 'message': the human readable message to be displayed.
+ */
+function field_default_validate($obj_type, $object, $field, $instance, $langcode, $items, &$errors) {
+  // Filter out empty values.
+  $items = _field_filter_items($field, $items);
+
+  // Check that the number of values doesn't exceed the field cardinality.
+  // For form submitted values, this can only happen with 'multiple value'
+  // widgets.
+  if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED && count($items) > $field['cardinality']) {
+    $errors[$field['field_name']][$langcode][0][] = array(
+      'error' => 'field_cardinality',
+      'message' => t('%name: this field cannot hold more than @count values.', array('%name' => t($instance['label']), '@count' => $field['cardinality'])),
+    );
+  }
+}
+
 function field_default_submit($obj_type, $object, $field, $instance, $langcode, &$items, $form, &$form_state) {
   $field_name = $field['field_name'];
 
@@ -30,7 +73,7 @@ function field_default_submit($obj_type,
   }
 
   // Filter out empty values.
-  $items = field_set_empty($field, $items);
+  $items = _field_filter_items($field, $items);
 }
 
 /**
Index: modules/field/field.form.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.form.inc,v
retrieving revision 1.36
diff -u -p -r1.36 field.form.inc
--- modules/field/field.form.inc	1 Dec 2009 03:07:33 -0000	1.36
+++ modules/field/field.form.inc	5 Dec 2009 19:55:17 -0000
@@ -141,7 +141,7 @@ function field_multiple_value_form($fiel
   // Determine the number of widgets to display.
   switch ($field['cardinality']) {
     case FIELD_CARDINALITY_UNLIMITED:
-      $filled_items = field_set_empty($field, $items);
+      $filled_items = _field_filter_items($field, $items);
       $current_item_count = isset($form_state['field_item_count'][$field_name])
                             ? $form_state['field_item_count'][$field_name]
                             : count($items);
Index: modules/field/field.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.module,v
retrieving revision 1.51
diff -u -p -r1.51 field.module
--- modules/field/field.module	4 Dec 2009 16:49:46 -0000	1.51
+++ modules/field/field.module	5 Dec 2009 20:00:38 -0000
@@ -304,23 +304,22 @@ function field_get_default_value($obj_ty
 }
 
 /**
- * Helper function to filter out empty values.
+ * Helper function to filter out empty field values.
  *
- * On order to keep marker rows in the database, the function ensures
- * that the right number of 'all columns NULL' values is kept.
- *
- * @param array $field
- * @param array $items
- * @return array
- *   returns filtered and adjusted item array
+ * @param $field
+ *   The field definition.
+ * @param $items
+ *   The field values to filter.
  *
- * TODO D7: poorly named...
+ * @return
+ *   The array of items without empty field values. The function also renumbers
+ *   the array keys to ensure sequential deltas.
  */
-function field_set_empty($field, $items) {
+function _field_filter_items($field, $items) {
   $function = $field['module'] . '_field_is_empty';
-  // We ensure the function is loaded, but explicitly break if it is missing.
   function_exists($function);
   foreach ((array) $items as $delta => $item) {
+    // Explicitly break if the function is undefined.
     if ($function($item, $field)) {
       unset($items[$delta]);
     }
Index: modules/field/modules/options/options.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/modules/options/options.module,v
retrieving revision 1.19
diff -u -p -r1.19 options.module
--- modules/field/modules/options/options.module	4 Dec 2009 16:49:46 -0000	1.19
+++ modules/field/modules/options/options.module	5 Dec 2009 19:43:58 -0000
@@ -115,20 +115,10 @@ function options_field_widget(&$form, &$
  * Form element validation handler for options element.
  */
 function options_field_widget_validate($element, &$form_state) {
-  $field = $form_state['complete form']['#fields'][$element['#field_name']]['field'];
-  $instance = $form_state['complete form']['#fields'][$element['#field_name']]['instance'];
-
   // Transpose selections from field => delta to delta => field, turning
   // multiple selected options into multiple parent elements.
   $items = _options_form_to_storage($element);
   form_set_value($element, $items, $form_state);
-
-  // Check that we don't exceed the allowed number of values.
-  if ($field['cardinality'] >= 2 && $field['cardinality'] != FIELD_CARDINALITY_UNLIMITED) {
-    if (count($items) > $field['cardinality']) {
-      form_error($element, t('%name: this field cannot hold more than @count values.', array('%name' => t($instance['label']), '@count' => $field['cardinality'])));
-    }
-  }
 }
 
 /**
Index: modules/field/modules/options/options.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/modules/options/options.test,v
retrieving revision 1.6
diff -u -p -r1.6 options.test
--- modules/field/modules/options/options.test	2 Dec 2009 19:26:21 -0000	1.6
+++ modules/field/modules/options/options.test	5 Dec 2009 19:43:58 -0000
@@ -85,7 +85,7 @@ class OptionsWidgetsTestCase extends Dru
     // Select first option.
     $edit = array("card_1[$langcode]" => 0);
     $this->drupalPost(NULL, $edit, t('Save'));
-    $this->assertListValues($entity_init, 'card_1', $langcode, array(0));
+    $this->assertFieldValues($entity_init, 'card_1', $langcode, array(0));
 
     // Check that the selected button is checked.
     $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
@@ -96,7 +96,7 @@ class OptionsWidgetsTestCase extends Dru
     // Unselect option.
     $edit = array("card_1[$langcode]" => '_none');
     $this->drupalPost(NULL, $edit, t('Save'));
-    $this->assertListValues($entity_init, 'card_1', $langcode, array());
+    $this->assertFieldValues($entity_init, 'card_1', $langcode, array());
 
     // Required radios with one option is auto-selected.
     $this->card_1['settings']['allowed_values'] = '99|Only allowed value';
@@ -145,7 +145,7 @@ class OptionsWidgetsTestCase extends Dru
       "card_2[$langcode][2]" => TRUE,
     );
     $this->drupalPost(NULL, $edit, t('Save'));
-    $this->assertListValues($entity_init, 'card_2', $langcode, array(0, 2));
+    $this->assertFieldValues($entity_init, 'card_2', $langcode, array(0, 2));
 
     // Display form: check that the right options are selected.
     $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
@@ -160,7 +160,7 @@ class OptionsWidgetsTestCase extends Dru
       "card_2[$langcode][2]" => FALSE,
     );
     $this->drupalPost(NULL, $edit, t('Save'));
-    $this->assertListValues($entity_init, 'card_2', $langcode, array(0));
+    $this->assertFieldValues($entity_init, 'card_2', $langcode, array(0));
 
     // Display form: check that the right options are selected.
     $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
@@ -185,7 +185,7 @@ class OptionsWidgetsTestCase extends Dru
     );
     $this->drupalPost(NULL, $edit, t('Save'));
     // Check that the value was saved.
-    $this->assertListValues($entity_init, 'card_2', $langcode, array());
+    $this->assertFieldValues($entity_init, 'card_2', $langcode, array());
 
     // Required checkbox with one option is auto-selected.
     $this->card_2['settings']['allowed_values'] = '99|Only allowed value';
@@ -227,7 +227,7 @@ class OptionsWidgetsTestCase extends Dru
     // Submit form: select first option.
     $edit = array("card_1[$langcode]" => 0);
     $this->drupalPost(NULL, $edit, t('Save'));
-    $this->assertListValues($entity_init, 'card_1', $langcode, array(0));
+    $this->assertFieldValues($entity_init, 'card_1', $langcode, array(0));
 
     // Display form: check that the right options are selected.
     $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
@@ -238,7 +238,7 @@ class OptionsWidgetsTestCase extends Dru
     // Submit form: Unselect the option.
     $edit = array("card_1[$langcode]" => '_none');
     $this->drupalPost('test-entity/' . $entity->ftid .'/edit', $edit, t('Save'));
-    $this->assertListValues($entity_init, 'card_1', $langcode, array());
+    $this->assertFieldValues($entity_init, 'card_1', $langcode, array());
 
     // A required select list does not have an empty key.
     $instance['required'] = TRUE;
@@ -281,7 +281,7 @@ class OptionsWidgetsTestCase extends Dru
     // Submit form: select first and third options.
     $edit = array("card_2[$langcode][]" => array(0 => 0, 2 => 2));
     $this->drupalPost(NULL, $edit, t('Save'));
-    $this->assertListValues($entity_init, 'card_2', $langcode, array(0, 2));
+    $this->assertFieldValues($entity_init, 'card_2', $langcode, array(0, 2));
 
     // Display form: check that the right options are selected.
     $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
@@ -292,7 +292,7 @@ class OptionsWidgetsTestCase extends Dru
     // Submit form: select only first option.
     $edit = array("card_2[$langcode][]" => array(0 => 0));
     $this->drupalPost(NULL, $edit, t('Save'));
-    $this->assertListValues($entity_init, 'card_2', $langcode, array(0));
+    $this->assertFieldValues($entity_init, 'card_2', $langcode, array(0));
 
     // Display form: check that the right options are selected.
     $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
@@ -308,7 +308,7 @@ class OptionsWidgetsTestCase extends Dru
     // Submit form: uncheck all options.
     $edit = array("card_2[$langcode][]" => array());
     $this->drupalPost(NULL, $edit, t('Save'));
-    $this->assertListValues($entity_init, 'card_2', $langcode, array());
+    $this->assertFieldValues($entity_init, 'card_2', $langcode, array());
 
     // Test the 'None' option.
 
@@ -316,12 +316,12 @@ class OptionsWidgetsTestCase extends Dru
     // as well.
     $edit = array("card_2[$langcode][]" => array('_none' => '_none', 0 => 0));
     $this->drupalPost('test-entity/' . $entity->ftid .'/edit', $edit, t('Save'));
-    $this->assertListValues($entity_init, 'card_2', $langcode, array(0));
+    $this->assertFieldValues($entity_init, 'card_2', $langcode, array(0));
 
     // Check that selecting the 'none' option empties the field.
     $edit = array("card_2[$langcode][]" => array('_none' => '_none'));
     $this->drupalPost('test-entity/' . $entity->ftid .'/edit', $edit, t('Save'));
-    $this->assertListValues($entity_init, 'card_2', $langcode, array());
+    $this->assertFieldValues($entity_init, 'card_2', $langcode, array());
 
     // A required select list does not have an empty key.
     $instance['required'] = TRUE;
@@ -362,7 +362,7 @@ class OptionsWidgetsTestCase extends Dru
     // Submit form: check the option.
     $edit = array("bool[$langcode]" => TRUE);
     $this->drupalPost(NULL, $edit, t('Save'));
-    $this->assertListValues($entity_init, 'bool', $langcode, array(0));
+    $this->assertFieldValues($entity_init, 'bool', $langcode, array(0));
 
     // Display form: check that the right options are selected.
     $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
@@ -371,33 +371,11 @@ class OptionsWidgetsTestCase extends Dru
     // Submit form: uncheck the option.
     $edit = array("bool[$langcode]" => FALSE);
     $this->drupalPost(NULL, $edit, t('Save'));
-    $this->assertListValues($entity_init, 'bool', $langcode, array(1));
+    $this->assertFieldValues($entity_init, 'bool', $langcode, array(1));
 
     // Display form: with 'off' value, option is unchecked.
     $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
     $this->assertNoFieldChecked("edit-bool-$langcode");
   }
-
-  /**
-   * Assert that a 'list' field has the expected values in an entity.
-   *
-   * @param $entity
-   *   The entity to test.
-   * @param $field_name
-   *   The name of the field to test
-   * @param $langcode
-   *   The language code for the values.
-   * @param $expected_values
-   *   The array of expected values.
-   */
-  function assertListValues($entity, $field_name, $langcode, $expected_values) {
-    $e = clone $entity;
-    field_attach_load('test_entity', array($e->ftid => $e));
-    $values = isset($e->{$field_name}[$langcode]) ? $e->{$field_name}[$langcode] : array();
-    $this->assertEqual(count($values), count($expected_values), t('Expected number of values were saved.'));
-    foreach ($expected_values as $key => $value) {
-      $this->assertEqual($values[$key]['value'], $value, t('Option @value was saved correctly.', array('@value' => $value)));
-    }
-  }
 }
 
Index: modules/field/tests/field.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/tests/field.test,v
retrieving revision 1.5
diff -u -p -r1.5 field.test
--- modules/field/tests/field.test	2 Dec 2009 19:26:22 -0000	1.5
+++ modules/field/tests/field.test	5 Dec 2009 19:55:04 -0000
@@ -39,6 +39,32 @@ class FieldTestCase extends DrupalWebTes
     }
     return $values;
   }
+
+  /**
+   * Assert that a field has the expected values in an entity.
+   *
+   * This function only checks a single column in the field values.
+   *
+   * @param $entity
+   *   The entity to test.
+   * @param $field_name
+   *   The name of the field to test
+   * @param $langcode
+   *   The language code for the values.
+   * @param $expected_values
+   *   The array of expected values.
+   * @param $column
+   *   (Optional) the name of the column to check.
+   */
+  function assertFieldValues($entity, $field_name, $langcode, $expected_values, $column = 'value') {
+    $e = clone $entity;
+    field_attach_load('test_entity', array($e->ftid => $e));
+    $values = isset($e->{$field_name}[$langcode]) ? $e->{$field_name}[$langcode] : array();
+    $this->assertEqual(count($values), count($expected_values), t('Expected number of values were saved.'));
+    foreach ($expected_values as $key => $value) {
+      $this->assertEqual($values[$key][$column], $value, t('Value @value was saved correctly.', array('@value' => $value)));
+    }
+  }
 }
 
 class FieldAttachTestCase extends FieldTestCase {
@@ -892,7 +918,7 @@ class FieldAttachOtherTestCase extends F
     $this->content = $output;
     $this->assertRaw($display, "Multiple formatter: all values are displayed, formatter settings are applied.");
 
-    // Test a formatter that uses hook_field_formatter_prepare_view()..
+    // Test a formatter that uses hook_field_formatter_prepare_view().
     $entity = clone($entity_init);
     $formatter_setting = $this->randomName();
     $this->instance['display'] = array(
@@ -1035,7 +1061,6 @@ class FieldAttachOtherTestCase extends F
     $values = array();
     for ($delta = 0; $delta < $this->field['cardinality']; $delta++) {
       $values[$delta]['value'] = -1;
-      $values[$delta]['_error_element'] = 'field_error_' . $delta;
     }
     // Arrange for item 1 not to generate an error
     $values[1]['value'] = 1;
@@ -1059,6 +1084,17 @@ class FieldAttachOtherTestCase extends F
       }
     }
     $this->assertEqual(count($errors[$this->field_name][$langcode]), 0, 'No extraneous errors set');
+
+    // Check that cardinality is validated.
+    $entity->{$this->field_name}[$langcode] = $this->_generateTestFieldValues($this->field['cardinality'] + 1);
+    try {
+      field_attach_validate($entity_type, $entity);
+    }
+    catch (FieldValidationException $e) {
+      $errors = $e->errors;
+    }
+    $this->assertEqual($errors[$this->field_name][$langcode][0][0]['error'], 'field_cardinality', t('Cardinality validation failed.'));
+
   }
 
   /**
@@ -1537,11 +1573,6 @@ class FieldFormTestCase extends FieldTes
     // Test with several multiple fields in a form
   }
 
-  // Check with a multiple widget (implement a textfield with comma separated values).
-
-  // Check inaccessible fields are preserved on update.
-  // Check inaccessible fields get default value on insert (not implemented yet).
-
   function testFieldFormJSAddMore() {
     $this->field = $this->field_unlimited;
     $this->field_name = $this->field['field_name'];
@@ -1597,6 +1628,46 @@ class FieldFormTestCase extends FieldTes
   }
 
   /**
+   * Tests widgets handling multiple values.
+   */
+  function testFieldFormMultipleWidget() {
+    // Create a field with fixed cardinality and an instance using a multiple
+    // widget.
+    $this->field = $this->field_multiple;
+    $this->field_name = $this->field['field_name'];
+    $this->instance['field_name'] = $this->field_name;
+    $this->instance['widget']['type'] = 'test_field_widget_multiple';
+    field_create_field($this->field);
+    field_create_instance($this->instance);
+    $langcode = LANGUAGE_NONE;
+
+    // Display creation form.
+    $this->drupalGet('test-entity/add/test-bundle');
+    $this->assertFieldByName("{$this->field_name}[$langcode]", '', t('Widget is displayed.'));
+
+    // Create entity with three values.
+    $edit = array("{$this->field_name}[$langcode]" => '1, 2, 3');
+    $this->drupalPost(NULL, $edit, t('Save'));
+    preg_match('|test-entity/(\d+)/edit|', $this->url, $match);
+    $id = $match[1];
+
+    // Check that the values were saved.
+    $entity_init = field_test_create_stub_entity($id);
+    $this->assertFieldValues($entity_init, $this->field_name, $langcode, array(1, 2, 3));
+
+    // Display the form, check that the values are correctly filled in.
+    $this->drupalGet('test-entity/' . $id . '/edit');
+    $this->assertFieldByName("{$this->field_name}[$langcode]", '1, 2, 3', t('Widget is displayed.'));
+
+    // Submit the form with more values than the field accepts.
+    $edit = array("{$this->field_name}[$langcode]" => '1, 2, 3, 4, 5');
+    $this->drupalPost(NULL, $edit, t('Save'));
+    $this->assertRaw('this field cannot hold more than 4 values', t('Form validation failed.'));
+    // Check that the field values were not submitted.
+    $this->assertFieldValues($entity_init, $this->field_name, $langcode, array(1, 2, 3));
+  }
+
+  /**
    * Tests fields with no 'edit' access.
    */
   function testFieldFormAccess() {
Index: modules/field/tests/field_test.field.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/tests/field_test.field.inc,v
retrieving revision 1.2
diff -u -p -r1.2 field_test.field.inc
--- modules/field/tests/field_test.field.inc	4 Dec 2009 16:49:46 -0000	1.2
+++ modules/field/tests/field_test.field.inc	5 Dec 2009 19:43:58 -0000
@@ -167,20 +167,56 @@ function field_test_field_widget_info() 
  * Implements hook_field_widget().
  */
 function field_test_field_widget(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
-  $element = array(
-    'value' => $element + array(
-      '#type' => 'textfield',
-      '#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : '',
-    ),
-  );
-  return $element;
+  switch ($instance['widget']['type']) {
+    case 'test_field_widget':
+      $element += array(
+        '#type' => 'textfield',
+        '#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : '',
+      );
+      return array('value' => $element);
+
+    case 'test_field_widget_multiple':
+      $values = array();
+      foreach ($items as $delta => $value) {
+        $values[] = $value['value'];
+      }
+      $element += array(
+        '#type' => 'textfield',
+        '#default_value' => implode(', ', $values),
+        '#element_validate' => array('field_test_widget_multiple_validate'),
+      );
+      return $element;
+  }
+}
+
+/**
+ * Form element validation handler for 'test_field_widget_multiple' widget.
+ */
+function field_test_widget_multiple_validate($element, &$form_state) {
+  $values = array_map('trim', explode(',', $element['#value']));
+  $items = array();
+  foreach($values as $value) {
+    $items[] = array('value' => $value);
+  }
+  form_set_value($element, $items, $form_state);
 }
 
 /**
  * Implements hook_field_widget_error().
  */
 function field_test_field_widget_error($element, $error) {
-  form_error($element['value'], $error['message']);
+  // @todo No easy way to differenciate widget types, we should receive it as a
+  // parameter.
+  if (isset($element['value'])) {
+    // Widget is test_field_widget.
+    $error_element = $element['value'];
+  }
+  else {
+    // Widget is test_field_widget_multiple.
+    $error_element = $element;
+  }
+
+  form_error($error_element, $error['message']);
 }
 
 /**
Index: modules/taxonomy/taxonomy.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.module,v
retrieving revision 1.545
diff -u -p -r1.545 taxonomy.module
--- modules/taxonomy/taxonomy.module	4 Dec 2009 16:49:47 -0000	1.545
+++ modules/taxonomy/taxonomy.module	5 Dec 2009 19:43:58 -0000
@@ -1045,17 +1045,6 @@ function taxonomy_field_validate($obj_ty
   $allowed_values = taxonomy_allowed_values($field);
   $widget = field_info_widget_types($instance['widget']['type']);
 
-  // Check we don't exceed the allowed number of values for widgets with custom
-  // behavior for multiple values (taxonomy_autocomplete widget).
-  if ($widget['behaviors']['multiple values'] == FIELD_BEHAVIOR_CUSTOM && $field['cardinality'] >= 2) {
-    if (count($items) > $field['cardinality']) {
-      $errors[$field['field_name']][$langcode][0][] = array(
-        'error' => 'taxonomy_term_illegal_value',
-        'message' => t('%name: this field cannot hold more that @count values.', array('%name' => t($instance['label']), '@count' => $field['cardinality'])),
-      );
-    }
-  }
-
   foreach ($items as $delta => $item) {
     if (!empty($item['tid'])) {
       if (!isset($allowed_values[$item['tid']])) {
