Skip to content
Snippets Groups Projects
Commit 86b838f0 authored by megachriz's avatar megachriz Committed by Megachriz
Browse files

Issue #2379631 by MegaChriz, cboyden, twistor, joelpittet, robhardwick,...

Issue #2379631 by MegaChriz, cboyden, twistor, joelpittet, robhardwick, dsnopek: fixed field_attach_validate() must be called before programmatic entity saves.
parent 0a18285e
No related branches found
No related tags found
No related merge requests found
......@@ -74,7 +74,7 @@ function date_feeds_set_target(FeedsSource $source, $entity, $target, array $val
$value = _date_feeds_get_date_object($value, $default_tz);
if (!$value || !empty($value->errors)) {
$field[$language][$delta][$value_key] = '';
$field[$language][$delta][$value_key] = NULL;
}
else {
if (!isset($field[$language][$delta]['timezone'])) {
......@@ -85,6 +85,15 @@ function date_feeds_set_target(FeedsSource $source, $entity, $target, array $val
$field[$language][$delta][$value_key] = $value->format($format, TRUE);
$field[$language][$delta][$offset_key] = $value->getOffset();
// Ensure that both value keys always exist to prevent php notices in
// date_field_validate().
if (!array_key_exists('value', $field[$language][$delta])) {
$field[$language][$delta]['value'] = NULL;
}
if (!array_key_exists('value2', $field[$language][$delta])) {
$field[$language][$delta]['value2'] = NULL;
}
}
$delta++;
......
......@@ -146,17 +146,76 @@ abstract class FeedsProcessor extends FeedsPlugin {
*/
protected function entityValidate($entity) {
$info = $this->entityInfo();
if (empty($info['entity keys']['language'])) {
return;
if (!empty($info['entity keys']['language'])) {
// Ensure that a valid language is always set.
$key = $info['entity keys']['language'];
$languages = language_list('enabled');
if (empty($entity->$key) || !isset($languages[1][$entity->$key])) {
$entity->$key = $this->entityLanguage();
};
}
// Ensure that a valid language is always set.
$key = $info['entity keys']['language'];
$languages = language_list('enabled');
// Perform field validation if entity is fieldable.
if (!empty($info['fieldable'])) {
try {
field_attach_validate($this->entityType(), $entity);
}
catch (FieldValidationException $e) {
$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 error message. If available, use the entity label to indicate
// which item failed. Fallback to the GUID value (if available) or else
// no indication.
$label = entity_label($this->entityType(), $entity);
if ($label || $label === '0' || $label === 0) {
$message = t("@error in item '@label':", array('@error' => $e->getMessage(), '@label' => $label));
}
elseif (!empty($entity->feeds_item->guid)) {
$message = t("@error in item '@guid':", array('@error' => $e->getMessage(), '@guid' => $entity->feeds_item->guid));
}
else {
$message = $e->getMessage();
}
// Compose the final error message and throw exception.
$message .= 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();
if (empty($entity->$key) || !isset($languages[1][$entity->$key])) {
$entity->$key = $this->entityLanguage();
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;
}
/**
......
"guid","title","created","alpha","beta","gamma","delta","epsilon","body"
1,"Lorem ipsum",1251936720,"Lorem",42,"4.2",3.14159265,1,"Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat."
2,"Ut wisi enim ad minim veniam",1251932360,"Ut wisi",32,"1.2",5.62951413,0,"Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat."
1,"Lorem ipsum",1251936720,"Lorem",42,"4.2",3.14159,1,"Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat."
2,"Ut wisi enim ad minim veniam",1251932360,"Ut wisi",32,"1.2",5.62951,0,"Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat."
......@@ -230,4 +230,253 @@ class FeedsMapperFieldTestCase extends FeedsMapperTestCase {
$this->assertNoText('delta_number_float_label');
}
/**
* 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 in item 'Ut wisi enim ad minim veniam'");
$this->assertText('alpha_text_label: the text may not be longer than 5 characters.');
}
/**
* Tests text field validation for nodes without a title.
*
* The error message should refer the GUID of an item if the entity has no
* label.
*/
public function testTextFieldValidationWithoutNodeTitle() {
// 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' => 'guid',
'target' => 'guid',
),
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 in item '2'");
$this->assertText('alpha_text_label: the text may not be longer than 5 characters.');
}
/**
* Tests text field validation for taxonomy terms.
*/
public function testTextFieldValidationForTaxonomyTerms() {
// Create vocabulary.
$edit = array(
'name' => 'Addams vocabulary',
'machine_name' => 'addams',
);
$this->drupalPost('admin/structure/taxonomy/add', $edit, t('Save'));
// Create a field with settings to validate.
field_create_field(array(
'field_name' => 'field_alpha',
'type' => 'text',
'settings' => array(
'max_length' => 5,
),
));
field_create_instance(array(
'field_name' => 'field_alpha',
'entity_type' => 'taxonomy_term',
'label' => 'alpha_text_label',
'bundle' => 'addams',
'widget' => array(
'type' => 'textfield',
),
));
// 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->setPlugin('csv', 'FeedsTermProcessor');
$this->setSettings('csv', 'FeedsTermProcessor', array('bundle' => 'addams'));
$this->addMappings('csv', array(
0 => array(
'source' => 'title',
'target' => 'name',
),
1 => array(
'source' => 'alpha',
'target' => 'field_alpha',
),
));
// Import CSV file.
$this->importFile('csv', $this->absolutePath() . '/tests/feeds/content.csv');
$this->assertText('Created 1 taxonomy term.');
$this->assertText('Failed importing 1 taxonomy term.');
$this->assertText("Field validation errors in item 'Ut wisi enim ad minim veniam'");
$this->assertText('alpha_text_label: the text may not be longer than 5 characters.');
}
/**
* Tests text field validation for users.
*/
public function testTextFieldValidationForUsers() {
// Create a field with settings to validate.
field_create_field(array(
'field_name' => 'field_alpha',
'type' => 'text',
'settings' => array(
'max_length' => 5,
),
));
field_create_instance(array(
'field_name' => 'field_alpha',
'entity_type' => 'user',
'label' => 'alpha_text_label',
'bundle' => 'user',
'widget' => array(
'type' => 'textfield',
),
));
// 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->setPlugin('csv', 'FeedsUserProcessor');
$this->addMappings('csv', array(
0 => array(
'source' => 'title',
'target' => 'name',
),
1 => array(
'source' => 'alpha',
'target' => 'field_alpha',
),
));
// Import CSV file. Users should fail to import because mail address is
// missing.
$this->importFile('csv', $this->absolutePath() . '/tests/feeds/content.csv');
$this->assertText('Failed importing 2 users.');
$this->assertText('User name missing or email not valid.');
$this->assertText("Field validation errors in item 'Ut wisi enim ad minim veniam'");
$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 in item 'Open Atrium Translation Workflow: Two Way Translation Updates'");
$this->assertText("Field validation errors in item 'Mapping Innovation at the World Bank with Open Atrium'");
$this->assertText("Field validation errors in item 'Open Data for Microfinance: The New MIXMarket.org'");
$this->assertText('alpha_text_label: this field cannot hold more than 6 values.');
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment