Method \Drupal\migrate\Plugin\migrate\process\MigrationLookup::transform() has two different return values:

  1. If the lookup succeeds it returns the result of \Drupal\migrate\Plugin\MigrateIdMapInterface::lookupDestinationId()
  2. If the lookup fails and stubbing is allowed it returns the result of \Drupal\migrate\Plugin\MigrateDestinationInterface::import()

The first is documented as:

   * @return array
   *   The destination identifier values of the record, or empty on failure.

The second as:

   * @return mixed
   *   The entity ID or an indication of success.

In practice the import() call always returns an array containing the entity id as the array key. While lookupDestinationId returns values numerically indexed.

This leads to the problems described in #2810907: Migrate SQL Map doesn't get array keys for compound keys
That ticket was apparently closed because it has workarounds for 2 situations:
- no stubs are present (you can use keys '0' and '1')
- all referenced content is stubbed (you can use keys 'id' and 'revision_id')

I'm opening this ticket for the case where you have both stubs and real content. You'll get the error 'Array index missing, extraction failed.'

CommentFileSizeAuthor
#37 2890690-37.patch65.7 KByogeshmpawar
#32 2890690-32.patch65.9 KBquietone
#31 interdiff.2890690.27-31.txt8.72 KBmikelutz
#31 2890690-31.drupal.MigrateLookup-plugin-has-inconsistent-return-values.patch65.95 KBmikelutz
#30 interdiff.2890690.22-27.txt3.02 KBmikelutz
#30 2890690-27.drupal.MigrateLookup-plugin-has-inconsistent-return-values.patch62.48 KBmikelutz
#27 2890690-27.drupal.MigrateLookup-plugin-has-inconsistent-return-values.patch62.48 KBmikelutz
#27 interdiff.2890690.22-27.txt3.02 KBmikelutz
#23 interdiff.2890690.21-22.txt726 bytesmikelutz
#23 2890690-22.drupal.MigrateLookup-plugin-has-inconsistent-return-values.patch60.53 KBmikelutz
#21 interdiff.2890690.19-21.txt48.55 KBmikelutz
#21 2890690-21.drupal.MigrateLookup-plugin-has-inconsistent-return-values.patch60.36 KBmikelutz
#19 interdiff.2890690.13-19.txt11.8 KBmikelutz
#19 2890690-19.drupal.MigrateLookup-plugin-has-inconsistent-return-values.patch12.14 KBmikelutz
#14 2890690-14.drupal.MigrateLookup-plugin-has-inconsistent-return-values.patch6.46 KBmikelutz
#13 2890690-13.drupal.MigrateLookup-plugin-has-inconsistent-return-values.patch3.2 KBmikelutz
#12 2890690-12.drupal.MigrateLookup-plugin-has-inconsistent-return-values.patch4.77 KBmikelutz
#11 2890690-11.drupal.MigrateLookup-plugin-has-inconsistent-return-values.patch4.7 KBmikelutz
migrate_lookup_consistent_keys.patch603 bytesJvE

Issue fork drupal-2890690

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

JvE created an issue. See original summary.

quietone’s picture

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

heddn’s picture

Issue summary: View changes
Status: Active » Needs work
Issue tags: +Needs tests

I fully understand the issue here. If we could provide a test of this, I think the fix proposed is a really great suggestion.

heddn’s picture

As a work around, can we use callback process plugin and call array_shift/array_pop?

mikelutz’s picture

I don't think so. At minimum it would trigger a warning, since callback uses call_user_func, which passes parameters by value, and array_shift/pop expect references.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

jibran’s picture

mikelutz’s picture

I'm curious as to what would break if the plugin simply returned an array with the results returned twice, under both keys. Struggling with a BC way to fix this other than adding a new optional config parameter to select the return keys, and leaving the current behavior alone if it is absent.

mikelutz’s picture

mikelutz’s picture

mikelutz’s picture

And one other option with a new configuration value instead.

mikelutz’s picture

Status: Needs work » Needs review

Alright, 13 breaks too much, not surprised, so let's throw 14 out for feedback.

joachim’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/migrate/src/Plugin/migrate/process/MigrationLookup.php
    @@ -31,6 +31,8 @@
    + * - return_associative: Returns multivalue keys in an associative array if true
    + *   and in an indexed array if false.
    

    This should be defined as optional, partly for BC, and also because it's easier to simply omit something rather than declare FALSE.

    Should also say what it's keyed by if you request associative.

  2. +++ b/core/modules/migrate/src/Plugin/migrate/process/MigrationLookup.php
    @@ -150,6 +152,8 @@ public static function create(ContainerInterface $container, array $configuratio
    +    $force_assoc = isset($this->configuration['return_associative']) && $this->configuration['return_associative'] == TRUE;
    

    (Can't wait for https://www.drupal.org/project/drupal/issues/2937177 to get in and remove the need for issets() all the time!)

mikelutz’s picture

In regards to both points, the issue is that (at least the way I structured this patch) omitting the configuration key is different than setting it to false. Omitting the key retains the current functionality (associative array if a stub is created and indexed if the lookup succeeds), while setting it to false returns an indexed array in either case.

I'm not a fan of this for several reasons, but I'm completely open to a better way to preserve BC while improving the functionality. In a perfect world, the plugin should return an associative array by default, and the extra configuration shouldn't be necessary, but I can't see a way to do that without breaking BC.

Another option would be to have two new configuration bools, force_associtive and force_indexed. This would allow the legacy behavior if both were false, but you have to deal with the error case where someone sets them both true.

You could have a configuration option that takes one of three predefined string keys, like return_array: associative|indexed|legacy. That effectively follows the same logic path as this patch, but perhaps with a slightly better DX. You could set the default to legacy and deprecate it, which basically returns us to this patch, where the param isn't really optional, because omitting it returns the current broken behavior that we want to get away from.

Plus all of this only comes into play if there are more than one destination id anyway, since (in yet another inconsistency), this plugin returns an array if there are multiple keys, and a single value if there is only one. Fortunately, you tend to know what your migrations destination ids are when you call this and admittedly, in the common case of just getting an entity_id back it's nice to be done in your process without going through an extract. But I wonder with new content moderation and workspaces initiatives, if it's not going to be more common to need an entity_id and revision id back.

Finally, we could combine this along with #2891073: MigrationLookup doesn't create stub when there's multiple migrations., #2890844: Migration Lookup plugin does not return multiple values when matched, #2804893: MigrationLookup process plugin not extensible, and possibly support for a lookup by migration tag, which I've also wanted to add, and create a brand new functional migrate_map_lookup plugin that works in a sane way and deprecate migration_lookup. Obviously a fair amount of work to update all the usages and tests in core, and I hate having 2 deprecated migrate_lookup plugins, but it might be worth it to have a consistent return array

I'd love to come up with a long term plan, I'm happy to try to do some work on it if we can figure out where we want to end up.

heddn’s picture

Discussed in migrate maintainers meeting with @phenaxproxima, @mikelutz, @maxocub, @quietone and @heddn. We suggested we'd like to use a config option for the process plugin to always return as a associative array and if that option isn't set, to trigger_error.

mikelutz’s picture

mikelutz’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
mikelutz’s picture

Status: Needs review » Needs work
mikelutz’s picture

mikelutz’s picture

I don't know that this is as cut and dried as I thought it would be. I was working on the assumption that all stubs return an associative array, but that isn't true. I'm not even sure that any core destination returns an associative array. most destinations extend off of the Entity destination, which returns [$entity_id]. ERR in contib returns an associative array of id and revision id, but that's the only one I see.

There's definitely a core issue here where the return value of stubbed and lookup values are different, but I'm suddenly less certain of the best way to resolve the discrepancy. I do like the way the migrations look when I switch them over to expecting a keyed array back from this plugin. it adds a little to the migration yml, but I think it becomes readable and more obvious what values you are looking at

At the end of the day, migrate_lookup doesn't get to control what DestinationPluginInterface::import() returns, we almost need to create the stub, and then call lookup destination ids again to guarantee the return values are indistinguishable, which may be what I have to do..

colan’s picture

Status: Needs work » Needs review

Let's see what the testbot says.

mikelutz’s picture

I've found several things failing since I posted that one. Not much point in running the testbot against it until I get a new version.

mikelutz’s picture

Status: Needs review » Needs work

The last submitted patch, 27: 2890690-27.drupal.MigrateLookup-plugin-has-inconsistent-return-values.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

mikelutz’s picture

mikelutz’s picture

quietone’s picture

Status: Needs work » Needs review
FileSize
65.9 KB

Needed a reroll

Status: Needs review » Needs work

The last submitted patch, 32: 2890690-32.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

esolitos’s picture

I've been using this patch, only for the change on class SubProcess, which seems to work as expected.

Very quick review of the other parts.

  1. +++ b/core/modules/aggregator/migrations/d6_aggregator_item.yml
    @@ -9,9 +9,15 @@ source:
    +      return_associatve: TRUE
    

    There's a typo in a few places: return_associatve should be return_associative

  2. +++ b/core/modules/aggregator/migrations/d7_aggregator_item.yml
    @@ -9,9 +9,15 @@ source:
    +      - fid
    

    Indentation issue.

yogeshmpawar’s picture

Assigned: Unassigned » yogeshmpawar
yogeshmpawar’s picture

Assigned: yogeshmpawar » Unassigned
Status: Needs work » Needs review
FileSize
65.7 KB

Rerolled the patch & comments addressed in #35

Status: Needs review » Needs work

The last submitted patch, 37: 2890690-37.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

jibran’s picture

The following point about the patch is not a bug but an enhancement so it might seem out of scope for the issue but I'd like to hear some thoughts on this and we can always create a follow-up.

For me, the overall change makes sense here but there is a disconnect between the input and the output. MigrateIdMapInterface::lookupDestinationId() allows associate array for IDs and currently there is no way to send the associated values array using MigrateLookup plugin to MigrateIdMapInterface::lookupDestinationId(). If we allowing retruned value to be an associate array then we should also allow MigrateLookup plugin to pass associate array for IDs MigrateIdMapInterface::lookupDestinationId() using $this->configuration or $value.

mikelutz’s picture

FYI, most of this is getting abstracted/refactored away in #3004927: Create Migration Lookup and Stub services

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

tvb’s picture

Migration from D7 site with translated nodes and no_stub: true:

MigrationLookup returns:

  • an entity_id if source langage of node matches source language of node in entity reference field.
  • an indexed array with an entity_id and the language prefix of the node in the entity reference field if the source languages do not match. The migration fails with [error] Value is not a valid entity. from EntityReference class.

Not sure whether this is a same, related or child issue.

A quick fix for this case (but not a solution) is to always return reset($destination_ids) in MigrationLookup.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

DieterHolvoet made their first commit to this issue’s fork.

DieterHolvoet’s picture

Status: Needs work » Needs review

I did a best effort rebase and committed it to a new MR. A lot changed since 8.8 so some things might not be right, but let's see what the test are saying. I tested manually with a custom migration and that seems to be working.

mikelutz’s picture

Status: Needs review » Closed (won't fix)

We aren't going to make changes here, closing this in favor of #3246666: Deprecate migrate_lookup and replace with cleaner process plugin

Rajeshreeputra made their first commit to this issue’s fork.

quietone’s picture

@DieterHolvoet, thanks for updating the patch but I don't see why a new MR was created after a migrate maintainer set the issue status to "won't fix". Credit stays because of the work in good faith on the initial patch update.

@Rajeshreeputra, this issue has a status of "won't fix". Adding an MR is of no help and causes unnecessary testing. Therefor, credit has been removed per How is credit granted for Drupal core issues.