3

I have multiple sources which roughly looks like:

  • Wines - Contents: "1,2,3,4"
  • Sodas - Contents: "1,2,3,4,5"

I'd like to combine those into one taxonomy vocabulary, get them to be auto-created and referenced in the destination field. So I'd like to do something like the following. But, if I read the static_map documentation correctly, mapping multiple sources like this is not the way it works. Also, I'm not yet exploding the string in the example, which I think is mandatory to be able to map the values.

  field_drinks:
    - 
      plugin: static_map
      source: 
        - wines
        - sodas 
      map: 
        wines:
          '1': 'Sauvignon Blanc'
          '2': 'Chiraz'
          '3': 'Pinot Noir'
          '4': 'Malbec'
        sodas:
          '1': 'Coca-Cola'
          '2': 'Spa'
          '3': 'Sprite'
          '4': 'Tonic'
          '5': 'Bitter lemon'
    -
      plugin: skip_on_empty
      method: process
    -
      plugin: entity_generate
      entity_type: taxonomy_term
      bundle_key: vid
      bundle: drinks
      value_key: name

How do I convert this to suit my needs?

7

Found it out after a lot of trial and error. Basically it comes down to breaking everything up into individual "pseudo fields" and prepare the data before processing it into the actual field:

process: 
  # First convert legacy wine id's to regular string names in a pseudo field
  _prepare_wines: 
    -
      plugin: explode
      limit: 100
      delimiter: ","
      source: wines
    -
      plugin: static_map
      map:
        '1': 'Sauvignon Blanc'
        '2': 'Chiraz'
        '3': 'Pinot Noir'
        '4': 'Malbec'

  # Secondly convert legacy soda id's to regular string names in a pseudo field
  _prepare_sodas: 
    -
      plugin: explode
      limit: 100
      delimiter: ","
      source: sodas
    -
      plugin: static_map
      map:
        '1': 'Coca-Cola'
        '2': 'Spa'
        '3': 'Sprite'
        '4': 'Tonic'
        '5': 'Bitter lemon'

  # Third, get all the pseudo field output together in a new pseudo field and flatten them into a single array
  _prepare_field_drinks:
    - 
      plugin: get
      source:
        - '@_prepare_wines'
        - '@_prepare_sodas'
    -
      plugin: flatten

  # Lastly, the data is now all in a nice single level array with only names for the new taxonomy terms so we can use those as source.
  field_drinks:
    -
      plugin: entity_generate
      entity_type: taxonomy_term
      bundle_key: vid
      bundle: drinks
      value_key: name
      source: '@_prepare_field_drinks'

Disclaimer: I'm not sure if this is the way it should be handled, but it seemed to do the trick without any custom plugins. Also, please be aware that if any of the source fields can be empty, you should prepend a skip_on_empty plugin to make sure your rows will not be ignored.

| improve this answer | |
3

Thank you Ambidex! You gave me the key I needed.

I had a similar problem: I needed to take a collection of independent Boolean variables from an external json feed and direct each into a single, existing, multi-valued taxonomy in Drupal 8. It seemed like a straightforward enough task that I decided to try using just the pre-existing process plugins.

This became more difficult as I discovered that the Boolean values could not be passed directly to a static_map with any ease (see: https://www.drupal.org/docs/8/api/migrate-api/migrate-process-plugins/process-plugin-static-map). In the end, I had to explicitly convert the booleans to strings, pass these to the static_map (one per taxonomy term), and then collect these all together, flattened, to hand off to the internal taxonomy. I was only interested in mapping those marked 'true' - so if false, we needed to skip setting anything. The end result was to be a series of checkboxes within a single vocabulary, checked if the incoming booleans were true.

Here's an example for anyone needing to do something similar:

_prepare_firstBooleanField:  
  -
    plugin: callback   
    callable: strtolower # a convenient method to do the conversion to string
    source: firstBooleanField
  -
    plugin: static_map
    bypass: true # skip mapping if the boolean value is false
    map:
     '1': 23 # to the left is the result of 
             # converting the boolean to string;
             # to the right is the taxonomy term id (tid)
             # to which we're mapping. Note that we do no mapping
             # at all for false - we just want to skip in that case.

_prepare_secondBooleanField:  # map as many of these as needed
  -
    plugin: callback   
    callable: strtolower
    source: secondBooleanField
  -
    plugin: static_map
    bypass: true 
    map:
      '1': 18 # etc - keep mapping tids (note: could also
              # map names, but this would require doing an 
              # entity_lookup later; if you know the term ids
              # (and we do, because we're mapping to an existing 
              # taxonomy) just use them directly. (It also allows
              # the names to change without breaking the import
              # for ongoing data feeds.)

# Now: flatten all the values that we've found together into 
# one simple array (thanks to the clue from Ambidex above)
_prepare_someTaxonomyField:
  -
    plugin: get
    source:
      - '@_prepare_firstBooleanField'
      - '@_prepare_secondBooleanField' # etc - can keep adding fields
  - 
    plugin: flatten

# Finally, hand the array to the taxonomy field! 
# By using the tids above, we can do a direct assignment: 
field_some_taxonomy: '@_prepare_someTaxonomyField'
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.