When you have multiple source migrations like this:

process:
  uid:
    plugin: migration_lookup
    migration: 
      - users
      - members
    source: author

the documentation says that

If the migration does not find the source ID in the migration map it will create a stub entity for the relationship to use. This stub is generated by the migration provided. In the case of multiple migrations the first value of migration list will be used, but you can select the migration you wish to use to create the stub

Even the code seems to suggest that that is the intention:

    if (!$destination_ids && ($self || isset($this->configuration['stub_id']) || count($migrations) == 1)) {
      // If the lookup didn't succeed, figure out which migration will do the
      // stubbing.
      if ($self) {
        $migration = $this->migration;
      }
      elseif (isset($this->configuration['stub_id'])) {
        $migration = $migrations[$this->configuration['stub_id']];
      }
      else {
        $migration = reset($migrations);
      }

But that last else can never be reached.
$destination_ids is empty so that part of the condition is satisfied.
count($migrations) equals 2 so the last part of the condition is ignored.
This means that either $self is true or $this->configuration['stub_id'] is set.
In the first case the top branch of the if/elseif/else is executed
In the second case the middle branch is executed.
The third can never be executed.

Workaround: specify a stub_id in your migration.

Issue fork drupal-2891073

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:

Comments

JvE created an issue. See original summary.

JvE’s picture

I updated the documentation page to refelect the actual current behaviour.

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.

mpp’s picture

I believe it's worse than that, if you look at how $self is set:

    foreach ($migrations as $migration_id => $migration) {
      if ($migration_id == $this->migration->id()) {
        $self = TRUE;
      }
      ...
    }

This means that if one of the migrations is the current one, stub_id is ignored, even if it is set explicitly. Which seems like a bug.

mpp’s picture

Status: Active » Needs review
StatusFileSize
new1.02 KB

The stub_id configuration should take precedence on the fact that the current migration is in the list of migrations.

In fact I doubt if the current migration being in the list has any meaning wrt the stubbing so perhaps we should delete it and take the first.

heddn’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests

OK, I think this really needs to start with some tests. I am pretty familiar with the issue we are facing here, and to figure out all the scenarios and make sure we don't break backwards compatibility, let's start with some tests.

mpp’s picture

Note that as JvE mentioned, the last else can never be reached, no need for tests to prove that but it would indeed be useful to have this covered by tests.

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.

mikelutz’s picture

I'm going to throw my hat into this one, starting with this test. This tests against the documented logic, asserting that in a single migration lookup, the single migration is used, and in a multiple migration lookup, the first migration in the list is selected unless 'stub_id' is set, in which case that migration is selected. If also asserts that the self migration is not a factor in this logic.

I'm going to follow it up with a patch that actually implements that logic just to see what regressions we have. The whole $self thing confuses me. As I was going through it, I thought for a while that it was put in as a way to select from a set of derivative migrations. since MigrationPluginManager::CreateInstances() will split a migration into its derivatives, If you lookup, say d7_node, and then have to go create a stub, you would probably need to pick a specific node migration to stub, to properly configure a destination plugin.

The problem is 'self' is a really bad way to try to select a derivative. It really has no bearing on which derivative you actually want to run, and if you don't configure the derivative specifically, 'self' doesn't seem like a much better choice than 'first'

It may have just come along since a self reference would be a typical use case for stubs, along with circular references, but again, not in the documentation, and no good reason. So, all I can think of to do is fix the 'bug' and see what breaks, and then decide from there if it needs some BC, or if anything it breaks is buggy in and of itself.

mikelutz’s picture

And here's a fix to match the documentation. It passes the migrate and migrate_drupal tests, but I haven't run it through the whole gambit, so no idea what might break.

mikelutz’s picture

6 failures is better than I expected. 4 are in the path module, they do a lookup against d6/7_node_translations with no stub id. Prior to the patch, these would not have created stubs because node_translations would be split into derived migrations, and fail to select one to stub. I think now that it is creating new translation node stubs, the expected node ids path's test's are checking for have all changed. adding 'no_stub:true' to the migration silences the errors, but I think it should actually be stubbing them, and the tests should be updated. I'm not certain where in the order that migration usually fires, so I don't know if it even matters outside the scope of the tests.

I'm looking into the 2 Functional tests as well to see if I can figure out what is going on with those.

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.

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.

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.

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.

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

ravi.shankar’s picture

StatusFileSize
new7.67 KB
new5.53 KB

Added reroll of patch #11 on Drupal 9.4.x.

huzooka’s picture

This problem is also about that for stubbing, the plugin should be able to identify which migration contains the source entry(entries) with the matching ID(s) before it actually tries to create the stub(s?).

We (@Wim Leers and I) tried to add this in #3156730: Stubs should only be created if the referenced source row actually exists, but because of the concerns core maintainers raised there we moved all of our work into Migrate Magician module. The migmag_lookup process plugin over there does exactly what @JvE needs imho.

codebymikey’s picture

Rerolled #11, essentially deprecating $self and making the stub_id more deterministic rather than relying on the first entry.

It should only create a stub if:

  • The stub_id is specified,
  • Or performing a single migration lookup

This reduces the amount of breaking changes as much as possible, and seems like a reasonable compromise rather than picking the first migration from the list to use as a stub.
We may choose to throw an exception if an appropriate stub could not be determined if no_stub is FALSE, causing the developer to fix their code.

@huzooka, thanks for the update. That module certainly looks promising, I'll be sure to look into it!

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.

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

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

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

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.