diff --git a/plugins/FeedsProcessor.inc b/plugins/FeedsProcessor.inc index 5dffc72..4bfd0d0 100644 --- a/plugins/FeedsProcessor.inc +++ b/plugins/FeedsProcessor.inc @@ -131,8 +131,45 @@ abstract class FeedsProcessor extends FeedsPlugin { field_attach_validate($this->entityType(), $entity); } catch (FieldValidationException $e) { - throw new FeedsValidationException(reset($e->errors)); + $errors = array(); + + // Unravel the errors inside the FieldValidationException. + foreach ($e->errors as $field_name => $field_errors) { + foreach ($field_errors as $langcode => $field_item_errors) { + $errors = array_merge($errors, $this->unravelFieldValidationExceptionErrors($field_item_errors)); + } + } + + // Compose the final error message and throw exception. + $message = $e->getMessage() . theme('item_list', array('items' => $errors)); + throw new FeedsValidationException($message); + } + } + + /** + * Helper function to unravel error messages hidden in a FieldValidationException. + * + * @param array $field_item_errors + * The errors for a single field item. + * + * @return array + * The unraveled error messages. + */ + protected function unravelFieldValidationExceptionErrors($field_item_errors) { + $errors = array(); + + foreach ($field_item_errors as $field_item_error) { + if (isset($field_item_error['message'])) { + // Found the error message! + $errors[] = $field_item_error['message']; + } + elseif (is_array($field_item_error)) { + // Error message is hidden deeper in the tree. + $errors = array_merge($errors, $this->unravelFieldValidationExceptionErrors($field_item_error)); + } } + + return $errors; } /** diff --git a/tests/feeds_mapper_field.test b/tests/feeds_mapper_field.test index 2506a29..d15dd8c 100644 --- a/tests/feeds_mapper_field.test +++ b/tests/feeds_mapper_field.test @@ -87,4 +87,96 @@ class FeedsMapperFieldTestCase extends FeedsMapperTestCase { $this->assertNodeFieldValue('gamma', '1.20'); $this->assertNodeFieldValue('delta', '5.62951'); } + + /** + * Tests text field validation. + */ + public function testTextFieldValidation() { + // Create a field with settings to validate. + $max_length = 5; + $typename = $this->createContentType(array(), array( + 'alpha' => array( + 'type' => 'text', + 'settings' => array( + 'field[settings][max_length]' => $max_length, + ), + ), + )); + + // Create and configure importer. + $this->createImporterConfiguration('Content CSV', 'csv'); + $this->setSettings('csv', NULL, array( + 'content_type' => '', + 'import_period' => FEEDS_SCHEDULE_NEVER, + )); + $this->setPlugin('csv', 'FeedsFileFetcher'); + $this->setPlugin('csv', 'FeedsCSVParser'); + $this->setSettings('csv', 'FeedsNodeProcessor', array('bundle' => $typename)); + $this->addMappings('csv', array( + 0 => array( + 'source' => 'title', + 'target' => 'title', + ), + 1 => array( + 'source' => 'alpha', + 'target' => 'field_alpha', + ), + )); + + // Import CSV file. + $this->importFile('csv', $this->absolutePath() . '/tests/feeds/content.csv'); + $this->assertText('Created 1 node'); + $this->assertText('Failed importing 1 node.'); + $this->assertText('Field validation errors'); + $this->assertText('alpha_text_label: the text may not be longer than 5 characters.'); + } + + /** + * Tests cardinality validation. + */ + public function testCardinalityValidation() { + // Create a field with settings to validate. + $cardinality = 6; + $typename = $this->createContentType(array(), array( + 'alpha' => array( + 'type' => 'text', + 'instance_settings' => array( + 'field[cardinality]' => $cardinality, + ), + ), + )); + + // Create and configure importer. + $this->createImporterConfiguration('Syndication', 'syndication'); + $this->setSettings('syndication', NULL, array( + 'content_type' => '', + 'import_period' => FEEDS_SCHEDULE_NEVER, + )); + $this->setPlugin('syndication', 'FeedsHTTPFetcher'); + $this->setPlugin('syndication', 'FeedsSyndicationParser'); + $this->setSettings('syndication', 'FeedsNodeProcessor', array('bundle' => $typename)); + $this->addMappings('syndication', array( + 0 => array( + 'source' => 'title', + 'target' => 'title', + ), + 1 => array( + 'source' => 'tags', + 'target' => 'field_alpha', + ), + )); + + // Import RSS. + // Three items of the RSS contain more than 6 categories. Because categories + // are mapped to field_alpha and field_alpha may only hold 6 values, they + // should fail to import. + $edit = array( + 'feeds[FeedsHTTPFetcher][source]' => $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'feeds') . '/tests/feeds/developmentseed.rss2', + ); + $this->drupalPost('import/syndication', $edit, 'Import'); + $this->assertText('Created 7 nodes'); + $this->assertText('Failed importing 3 nodes.'); + $this->assertText('Field validation errors'); + $this->assertText('alpha_text_label: this field cannot hold more than 6 values.'); + } }