Hi, thank you for the great work.
i dont know if this a bug or a feature request, but when i try the import mapping of users , Roles should be listed in select target drop down list and may be the langcode too for all entities that is supposed to be imported.
Thanks in advance for the great work i've been waiting for a long time for this mod. to port to D8.

CommentFileSizeAuthor
#28 interdiff-2933361-27-28.txt4.9 KBMegaChriz
#28 feeds-config-entityreference-2933361-28.patch70.84 KBMegaChriz
#27 interdiff-2933361-24-27.txt34.34 KBMegaChriz
#27 feeds-config-entityreference-2933361-27.patch70.47 KBMegaChriz
#24 interdiff-2933361-23-24.txt4.52 KBMegaChriz
#24 feeds-config-entityreference-2933361-24.patch42.12 KBMegaChriz
#23 interdiff-2933361-12-23.txt34.5 KBMegaChriz
#23 feeds-config-entityreference-2933361-23.patch42.07 KBMegaChriz
#14 select a target.png1.23 MBlomale@bluewin.ch
#12 feeds-config-entityreference-2933361-12.patch12.42 KBMegaChriz
#8 demo-user-with-role-field-imported-succesfully.png15 KBvijay.mayilsamy
#8 demo-user-csv.png15.48 KBvijay.mayilsamy
#8 Users-mapping-target-after-patch.png48.41 KBvijay.mayilsamy
#8 users-mapping-target-before-patch.png46.88 KBvijay.mayilsamy
#5 feeds-config-entityreference.patch5.26 KBMegaChriz
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

yassine makke created an issue. See original summary.

MegaChriz’s picture

Title: User Import mapping Roles should be listed in select target drop down » Add a role mapping target
Related issues: +#1376774: User Processor - add mapping target for user roles

Agreed. A role mapping target hasn't been implemented yet for the D8 version. Patches are welcome.

For reference, this was the equivalent issue for D7: #1376774: User Processor - add mapping target for user roles. Could be used to get ideas for how the role target should be implemented.

yassine makke’s picture

Hi thank you for the reply, i ended up using migration csv import which worked but after learning and searching a bit.
But with Feeds UI it could be a lot better and easier "i think".
thanks any way.

saranya ashokkumar’s picture

I am also looking for the role mapping. I created new feeds target as checkbox. But It is not showing in the mapping place.

Am I missed anything? Can anyone guide me what I have to do? My code is:

<?php

namespace Drupal\feeds\Feeds\Target;

use Drupal\feeds\Plugin\Type\Target\FieldTargetBase;

/**
 * Defines a checkboxes field mapper.
 *
 * @FeedsTarget(
 *   id = "checkboxes",
 *   field_types = {
 *     "checkboxes",
 *   }
 * )
 */
class Checkbox extends FieldTargetBase {

  /**
   * {@inheritdoc}
   */
  protected function prepareValue($delta, array &$values) {
    $values['value'] = trim($values['value']);
  }

}
MegaChriz’s picture

I think that "checkboxes" is not the field type of the roles field. "checkboxes" say something about how you input the roles field in the UI, thus the field widget. If you look at \Drupal\user\Entity\User::baseFieldDefinitions() you see that "roles" is an entity reference field:

$fields['roles'] = BaseFieldDefinition::create('entity_reference')
  ->setLabel(t('Roles'))
  ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED)
  ->setDescription(t('The roles the user has.'))
  ->setSetting('target_type', 'user_role');

A role entity is a configuration entity. Currently, Feeds only has support for entity reference fields that references content entities.

Luckily, I have been working on support for referencing config entities as well. Attached is a patch for that. I have not tested if it works for roles: I needed this Feeds target for an other entity reference field.

saranya ashokkumar’s picture

Hi MegaChriz,

It's working fine! Thank you so much.

kclarkson’s picture

Status: Active » Needs review

I have applied the patch to 8.x-3.x and was able to import user roles from a CSV.

User Role Feeds Notes:

  • One thing to note is that you need to add the machine name of the role in the excel spreadsheet.
  • After import, any previous roles are overwritten (removed) and the import role is assigned
  • Multiple roles in the same field will require the Tamper module
  • Used separate columns for role 1, role 2, role 3. Multiple roles where then assigned.
vijay.mayilsamy’s picture

Status: Needs review » Reviewed & tested by the community
FileSize
46.88 KB
48.41 KB
15.48 KB
15 KB

Hi All,

I have applied the patch and roles field appear in the target after applying the patch.
Tested by importing the users to the system with roles column added to the demo content.

Herewith i'm attaching the following files:

  1. Screenshot of the target dropdown before the patch
  2. Screenshot of the target dropdown after applying the patch
  3. Screenshot of Demo user csv
  4. Screenshot of the user info imported to the table

Changing the status to RTBC

Thanks
Vijay

jamesdixon’s picture

Thanks @vijay.mayilsamy! Code looks good to me from #5. Do we care there were a couple of failures in older versions of PHP?

PHP 5.5 & SQLite 3.8, D8.7 304 pass, 2 fail 
jamesdixon’s picture

With PHP5 end of life at the end of 2018 not sure fixing those 2 failed tests is a priority.

MegaChriz’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: -users +Needs tests

@jamesdixon
I think that test is a random test failure as it fails on:

Drupal\Core\Installer\Exception\AlreadyInstalledException:
To start over, you must empty your existing database and copy default.settings.php over settings.php.
To upgrade an existing installation, proceed to the update script.

I think there are two things left to do here:

  • We need an automated test for this new target.
  • Decide if we really want to revoke roles if not provided by the source. That it does so is consistent with other mappers though, but for the D7 version it was decided to special case the role target.
MegaChriz’s picture

Here's an updated patch with tests. Note that this patch doesn't only allow you to map to roles, but also to any other entity reference field that targets a config entity. New in this patch also is the possibility to reference by properties other than ID on the config entity. The data type of these properties need to be a string or an integer.

About the revoke roles issue: I think it's bad UX having other roles be revoked. Thus status remains "Needs work".

rcodina’s picture

Patch on #12 works for me. I have used it to map user roles. Many thanks @MegaChriz!

lomale@bluewin.ch’s picture

FileSize
1.23 MB

Hi
I'm coming back on this issue.
I used feeds an imported the users. but one thing didn't work. I wasn't able to map to roles.
does it mean that there is a patch, but the patch is not integrated in the current release.

I use Drupal 8.8.1 and feeds 8.x-3.0-alpha6

I added the pictures

select a target

what can I do. I not used to patch though I could run Drush. how would I have to patch #12

thanks for help Lothar

lomale@bluewin.ch’s picture

Priority: Normal » Major
MegaChriz’s picture

Issue tags: +beta blocker

Adding this as a beta blocker.

lomale@bluewin.ch’s picture

Sorry can you tell me what you mean by this. "Adding this as a beta blocker".

I would appreciate if you write down the sentence I have to use to add the patch to my testsite.

feeds-config-entityreference-2933361-12.patch

site/drupal_test

I would like to test that if it is useful and works for me.

Thanks

rcodina’s picture

@lomale Copy the patch file inside the module directory. Better if you use the latest dev version. Then do this:

patch -p1 < feeds-config-entityreference-2933361-12.patch

Please, give feedback about the patch.

boabjohn’s picture

#12 works for me...thanks heaps!!

rcodina’s picture

Status: Needs work » Reviewed & tested by the community
kierduros’s picture

It looks like the refactoring that went on for Alpha7 removed what the most recent patch in this thread was modifying to make user roles an importable aspect of the user record.

Any timeframe for when there'll be a new patch or when the functionality will get incorporated into a release? (I'd offer to help, but, well... if I could do it, I wouldn't be asking... I'd be posting a patch.)

(Or maybe my copy just isn't patching correctly at all... which wouldn't be unheard of with all the problems I've been having lately in my dev environment... ~sigh~)

Yep. Just my dev environment acting up.

When the patch is properly applied, it works great. Thanks.

MegaChriz’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs issue summary update

@kierduros
We are aiming to get this issue finalized by October 1 this year. The Feeds team is currently focussed on other issues and when some of these are done, this one will be the next in line.

Here’s a brief schema of what we’re working on right now:
https://docs.google.com/spreadsheets/d/1cn4vmHosTfxgyI0zlvVv_ce94715eH-m...

If you’re able to help out - especially on the Tamper issues - the chances that this issue actually gets done before October 1 will go up.

This issue could also use an issue summary update. What’s left to be done is noted in comment #11 and #12.

MegaChriz’s picture

Regarding the user role target, this ports the following from the D7 version of Feeds:

  • The option to only accept certain roles from the source (allowed roles);
  • Autocreate new roles;
  • The option to revoke roles that are not provided by the source (and don't revoke by default);
  • Several tests.

There's now a separate target for user roles and a more generic one for other config entity references.

Maybe needs an unit test for the new UserRole target.

MegaChriz’s picture

nevergone’s picture

Status: Needs review » Reviewed & tested by the community

Tested and works well!

Taiger’s picture

#24 worked for me.

I am on
Drupal core 8.9.11
Feeds 8.x-3.0-alpha9

This is an essential feature! Thank you!!

MegaChriz’s picture

Status: Reviewed & tested by the community » Needs review
FileSize
70.47 KB
34.34 KB

This patch adds unit tests for FeedsTarget plugins "ConfigEntityReference" and "UserRole".

It also changes/fixes the following:

  • An issue where roles were not autocreated when referencing roles by label.
  • When importing a non-allowed role, the error message was that the role wasn't found. The error message in this case is now "The role foo may not be referenced." and validation of the import fails in this case.
  • The option to autocreate roles is grayed out when referencing roles by something else than ID or label. Roles weren't created automatically anyway when not referencing by either of those two properties.
  • Unit tests for entity reference targets were refactored a bit, because of the high amount of similarities between the targets EntityReference, ConfigEntityReference and UserRole.
MegaChriz’s picture

This patches fixes coding style and also changes the error message for when a role could not be found.

The message was:

Referenced entity not found for field label with value Bar.

And now is:

The role Bar cannot be assigned because it does not exist.

I think this is ready (if tests still pass). I plan to commit it in a few days.

  • MegaChriz committed 1b377b5 on 8.x-3.x
    Issue #2933361 by MegaChriz, vijay.mayilsamy, rcodina, saranya...
MegaChriz’s picture

Component: Feeds Import (feature) » Code
Status: Needs review » Fixed
Issue tags: -Needs tests

Committed #28. Only one beta blocker to go!

Thank you all for testing.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

superlolo95’s picture

Hello,
Could you clarify me why there are 2 mappers for the entity_reference type?
For my custom module to work, I had to modifiy this mapper in order it be not used by my custom module (for entity_reference fields).
Thanks

MegaChriz’s picture

@superlolo95
There are actually three entity reference mappers:

  1. ConfigEntityReference, for fields referencing config entities;
  2. EntityReference, for fields referencing content entities;
  3. UserRole, for fields referencing config entities of type "user_role".

For config and content entity reference fields, there are different targets, because there are differences on how to handle the targets. For content entity reference fields, there's a setting to use a field to reference an entity by. Config entities don't have fields, so that target provides you options to select an entity by certain properties of the config entity instead.

Then there's the UserRole target, which extends ConfigEntityReference. The UserRole target has some extra configuration options. You can configure which roles Feeds should accept, if non-existing roles should be autocreated and if Feeds should also revoke existing roles on the user if the source doesn't provide them.

What issue did you experience with your custom module and which of the three entity reference targets did you need to modify? And what did you modify on it?

superlolo95’s picture

Hello
Thanks for the reply.
My custom module works on certain type of node.
I had to modify the ConfigEntityReference mapper. I change the parameter from entity_reference to config_entity_reference.
Otherwise, my module is using the ConfigEntityReference mapper instead of the EntityReference mapper.

My type of node is build as below

  1. Node type ==>person
  2. The "person" node type is having a paragraph field ==>work
  3. This "work" paragraph type is having an entity reference field that points to another node type==>establishment

node person:
--parapgraph work
------node establishment

The 3 step is where I am having troubles. The ConfigEntityReference mapper is used instead of the EntityReference mapper. Should I "disabled" the ConfigEntityReference mapper.
I do not get how feeds choose what mapper should be used.

MegaChriz’s picture

@superlolo95
Do you use additional modules for importing paragraphs? If so, which one? Maybe there’s an issue with that module that’s causing to using the wrong FeedsTarget plugin.

Do you import paragraphs separately (one feed type for paragraphs + one feed type for nodes) or alongside with nodes (one feed type for nodes and paragraphs combined)?

superlolo95’s picture

@MegaChriz,
I use a dedicated custom module to perform the import.
This import is done in a single shot, by this I mean a node (person) and a the associated paragraphs (work) are imported simoustaneously.
The nodes establishments are already existing and imported separately.
So my CSV lines (person+ work) are explode user tamper to extract the individual paragrahs (work) data.

What I do not get is how feeds select the mapper if there are multiple mappers for the entity_reference field type.
What I though was that feeds looks into all the existing mappers and take the first one that matches the current field type. And here as there 2 mappers with field_types = {"entity_reference"}, feeds does not know which one to select.
But I think I am missing something.

MegaChriz’s picture

@superlolo95

What I do not get is how feeds select the mapper if there are multiple mappers for the entity_reference field type.

  1. In \Drupal\feeds\Plugin\Type\Target\FieldTargetBase::targets(), each field on the entity type is checked if it matches what is defined in the annotation for "field_types" for the current FeedsTarget plugin:
    if (in_array($field_definition->getType(), $definition['field_types'])) {
    
  2. ::prepareTarget() gets called. Only if that returns something, a target gets added to the list of available targets.
    if ($target = static::prepareTarget($field_definition)) {
      $target->setPluginId($definition['id']);
      $targets[$id] = $target;
    }
    
  3. \Drupal\feeds\Feeds\Target\EntityReference::prepareTarget() only returns something if the entity type is a content entity type. See the entityClassImplements() call.
    /**
     * {@inheritdoc}
     */
    protected static function prepareTarget(FieldDefinitionInterface $field_definition) {
      // Only reference content entities. Configuration entities will need custom
      // targets.
      $type = $field_definition->getSetting('target_type');
      if (!\Drupal::entityTypeManager()->getDefinition($type)->entityClassImplements(ContentEntityInterface::class)) {
        return;
      }
    
      return FieldTargetDefinition::createFromFieldDefinition($field_definition)
        ->addProperty('target_id');
    }
    
  4. Similar, \Drupal\feeds\Feeds\Target\ConfigEntityReference::prepareTarget() only returns something if the entity type is a config entity type. Again, see the entityClassImplements() call.
    /**
     * {@inheritdoc}
     */
    protected static function prepareTarget(FieldDefinitionInterface $field_definition) {
      $type = $field_definition->getSetting('target_type');
      if (!\Drupal::entityTypeManager()->getDefinition($type)->entityClassImplements(ConfigEntityInterface::class)) {
        return;
      }
    
      return FieldTargetDefinition::createFromFieldDefinition($field_definition)
        ->addProperty('target_id');
    }
    
  5. When for a field a target is already defined, for next FeedsTarget plugins checks are skipped for that field. So the first FeedsTarget plugin that defines a target for a field, wins. See \Drupal\feeds\Plugin\Type\Target\FieldTargetBase::targets().
    foreach ($field_definitions as $id => $field_definition) {
      if (isset($targets[$id])) {
        continue;
      }
    
  6. UserRole::targets() completely overrides FieldTargetBase::targets(). It defines a target for each field that references entities of type 'user_role'.
    /**
     * {@inheritdoc}
     */
    public static function targets(array &$targets, FeedTypeInterface $feed_type, array $definition) {
      $processor = $feed_type->getProcessor();
    
      if (!$processor instanceof EntityProcessorInterface) {
        return $targets;
      }
    
      $field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions($processor->entityType(), $processor->bundle());
    
      foreach ($field_definitions as $id => $field_definition) {
        if ($field_definition->getType() == 'entity_reference' && $field_definition->getSetting('target_type') == 'user_role') {
          if ($target = static::prepareTarget($field_definition)) {
            $target->setPluginId($definition['id']);
            $targets[$id] = $target;
          }
        }
      }
    }
    

Does this clear up some things for you?

superlolo95’s picture

thanks a lot for the very detailed answered!
I will have a look at it, I think this will solve my issue.