Problem/Motivation

When using the MigrateSource plugin "d7_node", the source fields are hardcoded in Drupal\node\Plugin\migrate\source\d7\Node::fields().

The migrate_d2d module from Drupal 7 was intelligent enough to return all of the source fields that are defined doing a custom query of the field_config_instance table. This functionality does not appear to exist in Drupal 8 yet.

Steps to reproduce

Proposed resolution

Add getFieldLabels() method to FieldableEntity.

Remaining tasks

#17.3
#23.2
Write a test
Review
Commit

User interface changes

API changes

Data model changes

Release notes snippet

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

tom friedhof created an issue. See original summary.

mikeryan’s picture

Title: d7_node migration plugin does not get source fields » Node source plugins should report custom fields when node_type is specified
Version: 8.1.x-dev » 8.2.x-dev

Neither the D6 or D7 source plugin is reporting custom fields. Both should, when node_type is specified (it makes no sense without a specific node type to check for instances).

ckaotik’s picture

This shouldn't be too hard to implement. I've used this approach on a custom source for fieldable entities in D7, and assume it would work on nodes as well. It should work if we added something like this to the fields() function:

// Get Field API fields.
if (!empty($this->configuration['node_type'])) {
  $legacy_fields = $this->getFields('node', $this->configuration['node_type']);
}
else {
  $legacy_fields = $this->getFields('node');
}
foreach ($legacy_fields as $field_name => $instance) {
  $data = !empty($instance['data']) ? $instance['data'] : '';
  $data = unserialize($data);
  if (!empty($data['description'])) {
    $fields[$field_name] = $this->t('@field: @description', [
      '@field' => $data['label'],
      '@description' => @$data['description'],
    ]);
  }
  else {
    $fields[$field_name] = $this->t('@field', [
      '@field' => $data['label'],
    ]);
  }
}
ckaotik’s picture

Status: Active » Needs review
FileSize
899 bytes

I've attached a more compact version of the above suggestion. Note that this only applies to migrations using d7_node as source.
This also returns fields when no bundle is specified, in which case the user needs to discern whether the fields are actually available for the row being migrated (more flexibility for multi-bundle migrations, yay).

mikeryan’s picture

Assigned: Unassigned » mikeryan
mikeryan’s picture

Title: Node source plugins should report custom fields when node_type is specified » Fieldable entity source plugins should report custom fields
Assigned: mikeryan » Unassigned
Status: Needs review » Needs work
Issue tags: +Needs tests

This can be generalized, I think, to handle any fieldable entity that either has no bundles, or has a source bundle key in the source configuration. FieldableEntity could add

protected function getFieldLabels($entity_type, $bundle = NULL)

(better name suggestions welcome).

Thus, the node plugins could call

$fields += $this->getFieldLabels('node', isset($this->configuration['node_type']) ? $this->configuration['node_type'] : NULL);

And the user plugins could call

$fields += $this->getFieldLabels('user');

Once #2746671: CCK field data not available for D7 taxonomy term migrations lands, d7_taxonomy_term could do

$fields += $this->getFieldLabels('taxonomy_term', isset($this->configuration['vocabulary']) ? $this->configuration['vocabulary'] : NULL);

We'd also want to implement getFieldLabels() in the d6_node source plugin, although maybe that should be a follow-up issue.

ckaotik’s picture

Good point, however how do we explain the differences between fields(), getFields() and the new getFieldLabels()? Seems to me that the fields should already be provided in FieldableEntity::fields(). That, however, would require a unified key to determine the bundle (e.g. bundle instead of node_type/vocabulary etc.), or some other way to figure out the correct key. (It's probably somewhere in the source data, but a getBundleKey() or the likes would be more durable.)

mikeryan’s picture

The bundle key is not discoverable - besides the fact that there's no database artifact documenting entities the way we have field_config/field_config_instance for fields, note that 'node_type' is not the bundle key in the D7 table, but an arbitrary configuration option key name in d7_node.yml. Yes, it would be nice to settle on 'bundle' as the key (with a BC layer continuing to accept node_type for nodes), but let's make that a separate issue. Maybe not too late for #2746671: CCK field data not available for D7 taxonomy term migrations to switch from 'vocabulary' to 'bundle' to make that simpler...

We could have a getBundleKey() with a default of NULL for sources without bundles (or which have not implemented a source option for querying on the bundle), yes.

Yes, the default fields() in FieldableEntity could retrieve the fields, then the concrete source plugin could add them in after listing the non-field properties, e.g.

return $fields + parent::fields();

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.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 tags: +Needs reroll
heddn’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
FileSize
3.59 KB

I didn't do a re-roll as it was more easy to just take the hunk in the previous patch and respond to the feedback. Still needs tests.

mikeryan’s picture

Status: Needs review » Needs work

Needs work because needs tests.

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

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should 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.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should 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.

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

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should 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.

quietone’s picture

Rerolled this and changed getFieldLabels to always return an array plus translated the label because the values in fields() are translated.

I'd like to use MigrateSqlSourceTestBase for the test but that specializes in testing query().

joachim’s picture

Quick review:

  1. +++ b/core/modules/migrate_drupal/src/Plugin/migrate/source/d7/FieldableEntity.php
    @@ -37,6 +37,29 @@ protected function getFields($entity_type, $bundle = NULL) {
    +   * Returns the field labels for attached fields.
    

    It's been ages since I worked on D7... is 'attached fields' the correct terminology for what we call config fields on D8?

    At any rate, an extra line of docblock to explain what is meant by 'attached field' would help, as I imagine lots of developers will be in my position too of not remembering what this terminology means!

  2. +++ b/core/modules/migrate_drupal/src/Plugin/migrate/source/d7/FieldableEntity.php
    @@ -37,6 +37,29 @@ protected function getFields($entity_type, $bundle = NULL) {
    +   *   (optional) The bundle.
    

    This should say what it's going to do if $bundle is omitted.

  3. +++ b/core/modules/migrate_drupal/src/Plugin/migrate/source/d7/FieldableEntity.php
    @@ -37,6 +37,29 @@ protected function getFields($entity_type, $bundle = NULL) {
    +  protected function getFieldLabels($entity_type, $bundle = NULL) {
    

    I think this needs a clearer name. getAttachedFieldLabels(), maybe?

    (Though see comment on the first line of the docblock.)

> I'd like to use MigrateSqlSourceTestBase for the test but that specializes in testing query().

Hmm yes, the problem is that MigrateSqlSourceTestBase has the testSource() method which expects a data provider in non-abstract child classes, and which we're not interested it at all. In an ideal world, I'd suggest we move testSource() to a new child class. But LOTS of test classes across core inherit from MigrateSqlSourceTestBase, so that would hugely complicate this patch.

I'd say make the test for this issue inherit from MigrateSourceTestBase, and just copy the getDatabase() method over to it.

We can then file a follow-up to refactor the test classes.

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

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.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: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should 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: 8.9.x-dev » 9.2.x-dev

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

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

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

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should 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.

andypost’s picture

  1. +++ b/core/modules/migrate_drupal/src/Plugin/migrate/source/d7/FieldableEntity.php
    @@ -37,6 +37,29 @@ protected function getFields($entity_type, $bundle = NULL) {
    +  protected function getFieldLabels($entity_type, $bundle = NULL) {
    

    should use type-hints

  2. +++ b/core/modules/migrate_drupal/src/Plugin/migrate/source/d7/FieldableEntity.php
    @@ -37,6 +37,29 @@ protected function getFields($entity_type, $bundle = NULL) {
    +        $fields[$field_name] = $this->t($data['label']);
    

    it's weird t($data[label]) maybe label is already translated

quietone’s picture

Version: 9.4.x-dev » 9.5.x-dev
Issue summary: View changes
Issue tags: +Bug Smash Initiative
FileSize
5.28 KB
3.93 KB

This is a bug smash triage issue today.

I rerolled that patch and made changes for #17.1, #17.2 and #23.1. I am not running tests because it is not necessary yet, let's do that after there is new test.

#17.3. Not convinced the name change is the right thing to do, only because it is inconsistent with the existing method getFields() which gets the data for the fields attached to the entity.

But most importantly this needs a test.

Leaving as a bug because this is functionality that was in the D7 version of migrate.

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.

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.