web-dev-qa-db-fra.com

Combinez plusieurs sources dans un champ

J'ai plusieurs sources qui ressemblent à peu près à:

  • Vins - Contenu: "1,2,3,4"
  • Sodas - Contenu: "1,2,3,4,5"

Je voudrais les combiner en un seul vocabulaire taxonomique, les faire créer automatiquement et référencer dans le champ de destination. Je voudrais donc faire quelque chose comme ce qui suit. Mais, si je lis le static_map documentation correctement, le mappage de plusieurs sources comme celui-ci ne fonctionne pas comme cela. De plus, je n'explose pas encore la chaîne dans l'exemple, ce qui, selon moi, est obligatoire pour pouvoir mapper les valeurs.

  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

Comment puis-je convertir cela en fonction de mes besoins?

3
Ambidex

Je l'ai découvert après de nombreux essais et erreurs. Fondamentalement, cela revient à tout décomposer en "pseudo-champs" individuels et à préparer les données avant de les traiter dans le champ réel:

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: Je ne sais pas si c'est la façon dont cela devrait être géré, mais il semblait faire l'affaire sans aucun plugin personnalisé. Sachez également que si l'un des champs source peut être vide, vous devez ajouter un skip_on_empty plugin pour vous assurer que vos lignes ne seront pas ignorées.

6
Ambidex

Merci Ambidex! Tu m'as donné la clé dont j'avais besoin.

J'ai eu un problème similaire: je devais prendre une collection de variables booléennes indépendantes d'un flux json externe et les diriger chacune dans une taxonomie unique, existante et à plusieurs valeurs dans Drupal 8. Il semblait que une tâche assez simple que j'ai décidé d'essayer d'utiliser uniquement les plugins de processus préexistants.

Cela est devenu plus difficile car j'ai découvert que les valeurs booléennes ne pouvaient pas être transmises directement à une static_map avec facilité (voir: https://www.drupal.org/docs/8/api/migrate-api/migrate -process-plugins/process-plugin-static-map ). À la fin, j'ai dû convertir explicitement les booléens en chaînes, les passer à la static_map (une par terme de taxonomie), puis les rassembler tous ensemble, aplatis, pour passer à la taxonomie interne. J'étais seulement intéressé à cartographier ceux marqués "vrai" - donc si faux, nous devions ignorer la définition de quoi que ce soit. Le résultat final devait être une série de cases à cocher dans un vocabulaire unique, vérifiées si les booléens entrants étaient vrais.

Voici un exemple pour quiconque doit faire quelque chose de similaire:

_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'
3
Spartanicus