2

I am using Feeds to map a CSV file to user entities and have the "Update existing users" setting in place. Everything is going great, except for the Telephone field... as it currently stands, the Telephone module doesn't have support for Feeds.

There is a patch that works for saving a telephone number when creating a new user, but not when updating an existing user.

Here's a CSV example (excluding headers for simplicity) for a new user:

demo,demo@demo.com,1234567890

Here's a CSV example for updating that same user:

demo,demo@demo.com,4567890123

When changing the value of the telephone number in the CSV file, and running it through the importer again, Feeds (or someone else?) doesn't see any incoming changes to be applied, so it skips the import entirely saying:

"There are no new users."

I've been looking at the Feeds API to see what hooks are available, and thought hook_feeds_presave() would be a nice one, since it talks about "skipping" an entity, but this hook only gets fired when creating a new user.

The hook_feeds_before_update() function gets called each time, but I'm not seeing a way to indicate to Feeds whether or not a value has changed, and to proceed or skip.

I'm guessing I need to expand upon the patch with hook(s)/other to make a simple decision for Feeds, pseudo code e.g.

...
// If telephone number has changed, tell feeds its OK to update.
if ($feed_item_value != $entity->{$field_name}['und'][o]['value']) {
  $feeds->update = TRUE;
}
else {
  $feeds->update = FALSE;
}
...

How does a module, that provides a field, tell Feeds that it detects a change with the field's value and to update an entity? Or does feeds and the internal entity system automatically do this?

  • I guess in hook_feeds_before_update you can query the DB and and compare values and proceed if there is a change.. I don't have installed Drupal on my current machine but I will test when I get a chance – sam2de Oct 31 '14 at 20:21
  • Right... but how do I do that in hook_feeds_before_update(), what is the syntax? As I mentioned, looking through all the incoming arguments with dpm(), I don't see anything in regards to that. – tyler.frankenstein Nov 3 '14 at 18:30
3
+50

The Feeds module uses the FeedsProcessor object to define what it calls mapping targets for an entity to determine what fields are unique and what can be optionally be set unique in the feeds importer mapping settings UI. It then uses the method existingEntityId to determine if the mapping targets are unique.

In the case of users, the hook_feeds_plugins method for the feeds module tells feeds to use the class FeedsUserProcessor. This class has a method named getMappingTargets to say that the optional unique fields can be name and mail. In the mapping ui for the user feeds importer (admin/structure/feeds/user/mapping), you can set name and/or mail to be unique. The existingEntityId method in FeedsUserProcessor.inc determines if it has found a unique value. If so, and the importer is set to replace or update existing users, then the feeds record will be updated.

If you really wanted to work with telephone number as a unique field attached to a user, then you use implement hook_feeds_plugins, define your own FeedsProcessor and extend FeedsUserProcessor, and overwrite the getMappingTargets to add the field as an optional_unique entry, and overwrite existingEntityId to find other users with a matching telephone number.

However, it sounds like you don't need to do that. Make sure your user feeds import is set to update existing users, and that it is reading the csv file properly.

I went ahead and enabled telephone, installed the patch you mentioned, and was able to see a user be created, and then be updated with a different telephone number. My import file looked like this:

name,mail,telephone
demo,demo@demo.com,1234567890

and then this:

name,mail,telephone
demo,demo@demo.com,4567890123

And here is an export of the feed import:

$feeds_importer = new stdClass();
$feeds_importer->disabled = FALSE; /* Edit this to true to make a default feeds_importer disabled initially */
$feeds_importer->api_version = 1;
$feeds_importer->id = 'user';
$feeds_importer->config = array(
  'name' => 'User import',
  'description' => 'Import users from CSV file.',
  'fetcher' => array(
    'plugin_key' => 'FeedsFileFetcher',
    'config' => array(
      'direct' => FALSE,
      'allowed_extensions' => 'txt csv tsv xml opml',
      'directory' => 'public://feeds',
      'allowed_schemes' => array(
        0 => 'public',
      ),
    ),
  ),
  'parser' => array(
    'plugin_key' => 'FeedsCSVParser',
    'config' => array(
      'delimiter' => ',',
      'no_headers' => 0,
    ),
  ),
  'processor' => array(
    'plugin_key' => 'FeedsUserProcessor',
    'config' => array(
      'bundle' => 'user',
      'roles' => array(
        3 => 0,
      ),
      'update_existing' => '1',
      'status' => '1',
      'mappings' => array(
        0 => array(
          'source' => 'name',
          'target' => 'name',
          'unique' => 0,
        ),
        1 => array(
          'source' => 'mail',
          'target' => 'mail',
          'unique' => 1,
        ),
        2 => array(
          'source' => 'telephone',
          'target' => 'field_telephone:url',
          'unique' => FALSE,
        ),
      ),
      'defuse_mail' => 0,
      'update_non_existent' => 'skip',
      'input_format' => 'plain_text',
      'skip_hash_check' => 0,
    ),
  ),
  'content_type' => '',
  'update' => 0,
  'import_period' => '-1',
  'expire_period' => 3600,
  'import_on_create' => 1,
  'process_in_background' => 0,
);
  • Amazingly, I come back to this issue and it is working like a charm. I changed nothing over the weekend, and it works perfectly today. I've updated my answer to confirm the "Update existing users" setting was set. Thank you for this in depth answer regardless, you've revealed some of the interior workings of Feeds, and that is very helpful! – tyler.frankenstein Nov 5 '14 at 14:48
  • Thanks, Tyler! I'm glad it is working for you. I did at one point see the "There are no new users" message when I tried to import a file without column headers. I wonder if that happened once, and for some reason the import kept re-using that file. – Evil E Nov 6 '14 at 15:16
  • Yes very good point, I do believe that the import may get confused sometimes if you re-upload the file, and it has the exact same file name as the previous import. For consistency, I'll plan to time stamp the file name in the future so it is always unique when I re-upload it. – tyler.frankenstein Nov 6 '14 at 16:04
  • For anyone stuck trying to get this working, just setup the feed importer how you want it, then export it, change the field you want to be unique in the window provided (From FALSE to TRUE), then import an importer with overwrite checked. Done. – Grizly Sep 8 '17 at 5:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.