Skip to content

Instantly share code, notes, and snippets.

@rocketeerbkw
Last active June 23, 2023 18:42
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rocketeerbkw/239219a6493c2adee34fb7ceb5af2072 to your computer and use it in GitHub Desktop.
Save rocketeerbkw/239219a6493c2adee34fb7ceb5af2072 to your computer and use it in GitHub Desktop.
How to migrate multi-value link field in Drupal 8
<?php
class Example extends SourcePluginBase {
public function prepareRow(Row $row) {
parent::prepareRow($row);
// I do some data manipulation to end up with an array that looks like this,
// which I want to import into multi-value link field.
$links = [
[
'title' => 'Link 1',
'uri' => 'URI 1',
],
[
'title' => 'Link 2',
'uri' => 'URI 2',
],
[
'title' => 'Link 3',
'uri' => 'URI 3',
],
];
$row->setSourceProperty('links', $links);
}
}
id: example
label: 'Example'
source:
plugin: example
keys:
- iid
process:
type:
plugin: default_value
default_value: example
title: title
# This is a multi-value drupal core link field.
# I want to migrate title and uri for each link.
# See example.php source plugin in this gist.
# This does not work.
field_links: links
# This also does not work.
'field_links/title': 'links/title'
'field_links/uri': 'links/uri'
# This worked!
field_links:
plugin: iterator
source: links
process:
title: title
uri: uri
destination:
plugin: 'entity:node'
@benjifisher
Copy link

Thanks, that helped a lot!

I am migrating Paragraph entities. Since these are based on the Entity Reference Revisions (ERR) module, they require two fields: target_id and target_revision_id. After migrating text and image paragraphs in separate migrations, I used migration_lookup and then added both to a single, multiple-valued paragraph field like this:

process:
  temp_text:
    plugin: migration_lookup
    migration: blog_text
    no_stub: true
    source: guid
  temp_image:
    plugin: migration_lookup
    migration: blog_image
    no_stub: true
    source: guid
  field_paragraph:
    plugin: iterator
    source:
      - '@temp_text'
      - '@temp_image'
    process:
      target_id: '0'
      target_revision_id: '1'
destination:
  plugin: 'entity:node'

@dmurphy1
Copy link

Thanks, this was really helpful!

@electrokate
Copy link

This really helped me, thank you!

@heitoralthmann
Copy link

Another big THANK YOU!

@heitoralthmann
Copy link

A few extra examples using iterator's replacement, sub_process:

# Processing a multi value, plain-text field
field_name:
      plugin: sub_process
      source: 'Source-Field-Name'
      process:
        value: Name

And a more complex example here:

# Looping through source field values and creating taxonomy terms for each of them (bundle_key and value_key are both required in this scenario)
field_name:
    -
      plugin: skip_on_empty
      method: process
      source: 'Source-Field-Name'
    -
      plugin: sub_process
      process:
        target_id:
          plugin: entity_generate
          bundle: vocabulary_id
          value_key: name
          bundle_key: vid
          source: 'Looping-Item-Property-Name'
          entity_type: taxonomy_term
          ignore_case: true

@vacho
Copy link

vacho commented Jan 6, 2021

This is the code that nows run for me

process:
  ...
  destination_field_system_name:
    plugin: sub_process
    source: source_field_system_name
    process:
      uri: url
      title: title
      options: attributes

@esterwein
Copy link

esterwein commented Apr 25, 2021

banner:
    plugin: migration_lookup
    migration: homepage__paragraph_field_dinamy_banner_component
    no_stub: true
    source: banner_id
  services:
    plugin: migration_lookup
    migration: homepage__paragraph_field_services_component
    no_stub: true
    source: services_id
  life_events:
    plugin: migration_lookup
    migration: homepage__paragraph_field_life_events_component
    no_stub: true
    source: life_events_id
  news:
    plugin: migration_lookup
    migration: homepage__paragraph_field_dynamic_news_component
    no_stub: true
    source: news_id
  new:
    plugin: migration_lookup
    migration: homepage__paragraph_field_new_on_site_component
    no_stub: true
    source: new_id
  offices:
    plugin: migration_lookup
    migration: homepage__paragraph_field_offices_component
    no_stub: true
    source: offices_id
  bulk_reference:
    plugin: migration_lookup
    migration: homepage__paragraph_field_bulk_reference_component
    no_stub: true
    source: bulk_reference_id
  interested:
    plugin: migration_lookup
    migration: homepage__paragraph_field_interested_component
    no_stub: true
    source: interested_id
  field_home_page_components:
    plugin: sub_process
    source:
      - '@banner'
      - '@services'
      - '@life_events'
      - '@news'
      - '@new'
      - '@offices'
      - '@bulk_reference'
      - '@interested'
    process:
      target_id: '0'
      target_revision_id: '1'

After a lot of trying I came up with this solution and it works !!!!
Thank you :)

@PabloGMZILLI
Copy link

PabloGMZILLI commented Jun 23, 2023

For those who need to import from a CSV file, here's an example of how it worked for me:

I created a preprocess so that the links were in this format:

CSV file:

ExampleId,Links
17327,"Link Text 1,www.google.com|Link Text 2,www.google.com|Link Text 3,www.google.com|Link Text 4,www.google.com"

And in migrate I did it this way:

  link_items:
    - plugin: skip_on_empty
      source: Links
      method: process
    - plugin: explode
      delimiter: '|'
  field_buttons:
    - plugin: explode
      source: '@link_items'
      delimiter: ','
    - plugin: sub_process
      process:
        title: '0'
        uri: '1'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment