Problem/Motivation

This is part of #2507607: [META] Replace Cthulhu-forsaken load plugins with migration builders.

Currently, CCK field values are migrated using a pair of dynamically-loaded migrations (d6_cck_field_values and d6_cck_field_revision) with dedicated source plugins.

Once the builder plugin type is implemented, it will be possible to generate individual migrations for each node type, each detailing which fields should be migrated for that type. This means that the d6_cck_* migrations will be obsolete, but it also means that the responsibility of pulling field values from the database will fall on the d6_node source plugin.

Proposed Resolution

Write a patch that copies CCK field value retrieval logic into the d6_node source plugin (and, by extension, d6_node_revision). For now, this functionality should be in core alongside the existing CCK handling, which will be removed when the builder plugin type lands.

This will also serve as the model for handling fieldable entities in the Drupal 7 migration path -- entity source plugins should be responsible for retrieving the field values. (In the Drupal 7 migration path, this will probably be implemented as a trait since any entity type can have fields. But for Drupal 6, it can be confined to the node source plugin.)

Remaining Tasks

Review and commit the patch.

API/UI Changes

None.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

phenaproxima’s picture

Status: Needs review » Needs work

The last submitted patch, migrate_drupal-node-cck.patch, failed testing.

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
21.56 KB
2 KB

Note to self: don't try to do logic in the constructor. It leads to the dark side. (At least in the case of migrations, where just installing one will instantiate the source and destination plugins.)

Status: Needs review » Needs work

The last submitted patch, 3: 2538000-3.patch, failed testing.

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
21.99 KB
778 bytes

C'mon, testbot, don't be like that...

phenaproxima’s picture

Added a test, and fixed a few bugs revealed by it.

Status: Needs review » Needs work

The last submitted patch, 6: 2538000-6.patch, failed testing.

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
8.29 KB

OK -- I'm totally abandoning my previous approach, which was to make the d6_field plugin the canonical source for field and field instance data. It's just too painful to try to invoke a source plugin from within another source plugin -- Migrate's architecture makes this extraordinarily difficult to do, much less test.

This new patch simply has d6_node read CCK information directly from the DB, no middleman required. All the methods I added for this have individual unit tests (in NodeTest) and could easily be moved into a trait if needed.

The changes between this and #6 are seismic enough that an interdiff would be more confusing than revealing, so I haven't included one. Consider this patch a reboot of the issue.

Status: Needs review » Needs work

The last submitted patch, 8: 2538000-8.patch, failed testing.

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
8.29 KB
656 bytes

As they said in the original 1968 version of The Producers: "[Here's] to failure!"

Status: Needs review » Needs work

The last submitted patch, 10: 2538000-10.patch, failed testing.

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
8.5 KB
984 bytes

Okay, well, the tests are passing locally for me now...

quietone queued 12: 2538000-12.patch for re-testing.

Status: Needs review » Needs work

The last submitted patch, 12: 2538000-12.patch, failed testing.

quietone’s picture

Status: Needs work » Needs review
FileSize
8.48 KB

re-roll.

quietone’s picture

I was going to change assertSame to assertIdentical and possibly add more tests. However, I'm not able to reach any breakpoint in the test. How do I run this test?

quietone’s picture

Status: Needs review » Needs work
quietone’s picture

RIght, just learned that PHPUnit doesn't have assertIdentical.

Berdir’s picture

assertSame() in phpunit is the same as assertIdentical() in simpletest.

quietone’s picture

Status: Needs work » Needs review
FileSize
8.9 KB
955 bytes

Added some tests

benjy’s picture

As long as we can migrate nodes without the the CCK module we can combine those. Looks like it's been handled by the moduleExists() call?

For now, this functionality should be in core alongside the existing CCK handling, which will be removed when the builder plugin type lands.

What is meant by this in the IS?

+++ b/core/modules/node/src/Plugin/migrate/source/d6/Node.php
@@ -115,10 +122,122 @@ public function prepareRow(Row $row) {
+    return @($this->fieldInfo[$node_type] ?: []);

What's the @ for?

phenaproxima’s picture

What is meant by this in the IS?

When I wrote that, I meant to say that the dedicated CCK migrations (and CCK plugins) will be removed from core shortly after builders land, so we need to get this patch in ASAP.

What's the @ for?

The ?: operator will produce an E_NOTICE if $this->fieldInfo[$node_type] is undefined, so the @ is there to silence that. It's a more concise way of saying isset($this->fieldInfo[$node_type]) ? $this->fieldInfo[$node_type] : []. In PHP 7, the same thing will be doable with the ?? operator.

benjy’s picture

The ?: operator will produce an E_NOTICE if $this->fieldInfo[$node_type] is undefined, so the @ is there to silence that.

I feared as much, I don't think this is a pattern we use in core.

phenaproxima’s picture

Status: Needs review » Needs work
Issue tags: +Migrate critical, +blocker

This blocks #2549013: Remove load plugins and is therefore a Migrate-critical blocker.

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
8.93 KB
436 bytes

Corrected the syntax.

benjy’s picture

Few small things:

  1. +++ b/core/modules/node/src/Plugin/migrate/source/d6/Node.php
    @@ -115,10 +122,122 @@ public function prepareRow(Row $row) {
    +        // @TODO Massage the field values so that field_foo_value becomes
    +        // just 'value', and so forth.
    

    Does this need an issue?

  2. +++ b/core/modules/node/src/Plugin/migrate/source/d6/Node.php
    @@ -115,10 +122,122 @@ public function prepareRow(Row $row) {
    +  /**
    ...
    +  protected function getFieldInfo($node_type) {
    

    Missing functiond oc.

  3. +++ b/core/modules/node/tests/src/Unit/Plugin/migrate/source/d6/NodeTest.php
    @@ -108,6 +108,42 @@ class NodeTest extends MigrateSqlSourceTestCase {
    +        'global_settings' => 'a:6:{s:6:"prefix";s:3:"id-";s:6:"suffix";s:0:"";s:3:"min";s:3:"100";s:3:"max";s:3:"200";s:14:"allowed_values";s:0:"";s:18:"allowed_values_php";s:0:"";}',
    ...
    +        'db_columns' => 'a:1:{s:5:"value";a:3:{s:4:"type";s:5:"float";s:8:"not null";b:0;s:8:"sortable";b:1;}}',
    ...
    +        'widget_settings' => 'a:2:{s:13:"default_value";a:1:{i:0;a:2:{s:5:"value";s:3:"101";s:14:"_error_element";s:47:"default_value_widget][field_test_four][0][value";}}s:17:"default_value_php";N;}',
    +        'display_settings' => 'a:7:{s:6:"weight";s:1:"3";s:6:"parent";s:0:"";i:5;a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}s:5:"label";a:1:{s:6:"format";s:5:"above";}s:6:"teaser";a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}s:4:"full";a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}i:4;a:2:{s:6:"format";s:7:"default";s:7:"exclude";i:0;}}',
    

    Might be worth expanding these

phenaproxima’s picture

Status: Needs review » Needs work

The d6_node builder also needs to be extended to merge CCK fields into the d6_node migration variants: see https://www.drupal.org/node/2549013#comment-10240207.

phenaproxima’s picture

Status: Needs work » Needs review
FileSize
7.63 KB
6.1 KB

Looks like it's already there, so I think this is good to go.

#26-1: Nope; I put that functionality into this new patch.
#26-2: Fixed.
#26-3: Most of those aren't needed for the test, so I just turned them into empty arrays.

I also removed several direct tests of protected methods on the D6 Node source; @benjy gave me a come-to-Jesus explanation of why directly testing protected methods is wrong.

Just to be clear, this completely obviates the need for the d6_cck_field_values and d6_cck_field_revision migrations. One of the only blockers left before we can kick load plugins out.

Status: Needs review » Needs work

The last submitted patch, 28: 2538000-28.patch, failed testing.

mikeryan queued 28: 2538000-28.patch for re-testing.

The last submitted patch, 28: 2538000-28.patch, failed testing.

mikeryan’s picture

So, this is dying due to memory consumption:

Memory usage is 272.14 MB (85% of limit 320 MB), reclaiming memory	
Memory usage is now 272.11 MB (85% of limit 320 MB), not enough reclaimed, starting new batch

In my local environment, also with a memory_limit of 320M, it works fine. Two obvious possibilities:

  1. The patch is causing causing excessive memory usage (a loop repeatedly migrating stuff?).
  2. The memory usage for entities in general has gone beyond the threshold where we can import the full D6 dump in one process.

I've submitted #2281393: D6->D8 Blocks - Custom titles not imported for retest as a control - if it succeeds, that suggests #1, if it fails it suggests #2. If it's #2, that raises the urgency of #2503999: Large volume entity migrations run out of memory.

mikeryan’s picture

Well #2281393: D6->D8 Blocks - Custom titles not imported failed, but with an entirely different error - MigrateDrupal6Test passed, no memory problem, which suggests that the patch here is somehow triggering more memory consumption. But, as I said, it works locally with the same memory_limit...

webchick’s picture

Priority: Normal » Major

This is blocking #2549013: Remove load plugins which in turn blocks Comment/Taxonomy content migrations for D7 => D8.

benjy’s picture

When we added builders they were meant to be alongside load plugins, I don't see why we *have* to remove load plugins to do comment/taxonomy, the existing API should work to complete those D7/D8 migrations we still have LoadTermNode although as an example.

It's a shame we did the builders and attempted to remove load plugins in 8.0 that has taken a long time and held up many of the D7 migrations.

mikeryan’s picture

phenaproxima can speak to the specifics of how the load plugins are blocking the D7 migrations, but my understanding was always that the intention of builders was to get rid of the load plugins. The genesis of the builders was #2507607: [META] Replace Cthulhu-forsaken load plugins with migration builders, after all.

phenaproxima queued 28: 2538000-28.patch for re-testing.

The last submitted patch, 28: 2538000-28.patch, failed testing.

phenaproxima queued 28: 2538000-28.patch for re-testing.

phenaproxima’s picture

Status: Needs work » Needs review
benjy’s picture

Sure, the plan is to get rid of load plugins but that's more work and if time is short we could not do that. builders transform the migrations before they're run, load plugins can still do that at run time today so they are both able to solve the term/cck problems in their own way. However, if there is time to get builders done and remove load plugins great.

phenaproxima’s picture

Here's a version that removes the d6_cck_field_values and d6_cck_field_revision migrations, which are obviated by this patch and which will make it easier to kill load plugins once this lands.

mikeryan’s picture

  1. +++ b/core/modules/node/src/Plugin/migrate/source/d6/Node.php
    @@ -115,10 +122,131 @@ public function prepareRow(Row $row) {
    +    if ($this->moduleExists('content') && $this->getModuleSchemaVersion('content') >= 6001) {
    

    Might be good to document the magic 6001 schema version here (presumably CCK changed its schema in such a way we don't want to try to support the previous version?).

  2. +++ b/core/modules/node/src/Plugin/migrate/source/d6/Node.php
    @@ -115,10 +122,131 @@ public function prepareRow(Row $row) {
    +            if (strpos($column, $field) === 0) {
    ...
    +      foreach (array_keys($field['db_columns']) as $column) {
    

    This seems problematic if there's a field whose name is the prefix for another field name - this is an issue for migrate_d2d as well (#2078913: D5 to D7 migration fails if one source CCK field is a substring of another). See below...

  3. +++ b/core/modules/node/src/Plugin/migrate/source/d6/Node.php
    @@ -115,10 +122,131 @@ public function prepareRow(Row $row) {
    +    $db = $this->getDatabase()->schema();
    

    $db sounds like it's referencing a database - perhaps $db_schema to be clear?

  4. +++ b/core/modules/node/src/Plugin/migrate/source/d6/Node.php
    @@ -115,10 +122,131 @@ public function prepareRow(Row $row) {
    +        $query->addField('t', $field['field_name'] . '_' . $column);
    

    Can we use '__' as the separator here, and use that above to recognize when a column is prefixed by the right field?

phenaproxima’s picture

1. I would have if I knew what the deal was with it, but I lifted that almost directly out of the CckFieldValues source, which doesn't document it either.

2. Shouldn't happen; the values are queried separately for each field, so by the time they reach prepareRow() $values should look like this:

array(
  'field_foo' => array(
    array('value' => 'bar', 'column2' => 'baz'),
  ),
  'field_bar' => array(
    array('value' => 'wambooli'),
  ),
)

3. I felt that it read better as "DB table exists" instead of "DB schema table exists", but I can rename it if you want.

4. Can't change the separator, because I'm adding a column that actually exists in the DB table. field_foo_value will exist, but field_foo__value won't. :)

mikeryan’s picture

Status: Needs review » Reviewed & tested by the community

It does help to have the CCK removal in here, so we can see that the node CCK code didn't come out of thin air, the logic has moved (and it also helps to see the loc-- benefit).

I've tested this with my own site using migrate_upgrade - my fields migrated successfully within the node migrations, without those separate field-only migrations, that's great! Code looks good - I'm ready to see this go in!

webchick’s picture

Status: Reviewed & tested by the community » Fixed
 9 files changed, 176 insertions(+), 728 deletions(-)

Hot damn!

Read through the non-deleted parts of this patch, nothing much stood out.

Asked a few minor questions in IRC, got them answered, this looks good to go, and unblocks all kinds of other stuff, so let's get 'er done!

Committed and pushed to 8.0.x. Thanks!

  • webchick committed 6ad0357 on 8.0.x
    Issue #2538000 by phenaproxima, quietone, benjy, mikeryan: The d6_node...
phenaproxima’s picture

Follow-up issue created for preserving the assertions from MigrateCckFieldValuesTest and MigrateCckRevisionTest: #2557557: Move old CCK assertions into MigrateNodeTest

quietone’s picture

Awesome!

For the first ever my tiny d6 site, 5 nodes and some CCK fields, actually migrated. Previously, the fields would be created but not the value. Today I have values! And for a file field too!

For me, it feels like I can do some serious testing now.

webchick’s picture

Wow, that's awesome!! :D Great news, quietone, and thanks so much for all your help!

quietone’s picture

Seems I spoke to soon. File uploads are working but not file fields.

Status: Fixed » Closed (fixed)

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