web-dev-qa-db-fra.com

Comment puis-je "former des champs" dans un paragraphe imbriqué, selon l'endroit où le champ est utilisé

J'ai ces types d'entités:

  • Un type de nœud: nodepage
  • Un type de paragraphe: pg_a
  • Un type de paragraphe: pg_b
  • Un type de paragraphe: pg_child

J'ai un modèle de contenu qui est:

nodepage
  ->field_a
    Referenced bundles: pg_a
      ->field_child
        Referenced bundles: pg_child
  ->field_b
    Referenced bundles: pg_b
      ->field_child
        Referenced bundles: pg_child

Tu peux voir ça pg_a et pg_b les deux ont un champ appelé field_child qui permet une référence à pg_child. Cela a une grande signification sémantique pour l'architecture du site.

Maintenant, quelque chose que je voudrais faire est de modifier l'algorithme pg_child, mais niquement lorsqu'il est référencé à partir de pg_a et non de pg_b.

Dans hook_field_widget_form_alter, où je pense Je devrais faire mes modifications, je peux faire ce qui suit:

$field_definition = $context['items']->getFieldDefinition();

// Get the current field widget being built, eg `field_child_thing`.
$name = $field_definition->getName();

// Get the bundle, ie. `pg_child`
$targetBundle = $field_definition->getTargetBundle();

// Get the bundle that $targetBundle is attached to in this instance...
$instance = ???

Je pensais que je pouvais approfondir la variable $ context, mais jusqu'à présent, cela m'a fait allusion. Jusqu'à présent, le meilleur candidat est #parents dans le formulaire, mais lorsque je ne trouve qu'une référence à field_child ce qui est ambigu.

Je soupçonne maintenant que je peux injecter plus de $ context de quelque part, peut-être dans la version parent.

3
simesy

Dans ce scénario, nous avons field_caption utilisé à divers endroits dans un paragraphe cta. L'entreprise a demandé de limiter field_caption à 25 carats, mais uniquement lorsqu'il est utilisé dans un nœud sur un champ de référence d'entité appelé field_foo_cta.

Tout d'abord, nous ajoutons un rappel #process au widget en fonction de la règle, en implémentant hook_field_widget_form_alter:

function mymodule_field_widget_form_alter(&$element, FormStateInterface $form_state, &$context) {
  $field_definition = $context['items']->getFieldDefinition();

  if ($field_definition instanceof FieldConfig) {
    $config = $field_definition->id();
    list ($entity_type, $bundle, $field_name) = explode('.', $config);

    if ($entity_type == 'paragraph' && $field_name == 'field_caption') {
      $element['#process'][] = ['\Drupal\mymodule\BusinessRules', 'alterFieldCaption'];
    }

  }
}

Ensuite, nous créons une nouvelle classe dans le répertoire src du module.

namespace Drupal\mymodule;

class BusinessRules {

  public static function alterFieldCaption(array &$element, FormStateInterface &$form_state, array &$complete_form) {

    // Use whatever logic to target instances of `field_caption`.
    if (reset($element['#parents']) == 'field_foo_cta') {
      $element['value']['#maxlength'] = 25;
    }
    return $element;

  }

}

Merci à @larowlan pour son aide.

3
simesy

Je pensais que je pouvais approfondir la variable $ context, mais jusqu'à présent, cela m'a fait allusion. Le meilleur candidat jusqu'à présent est #parents dans le formulaire, mais quand je ne trouve qu'une référence à field_child qui est ambiguë.

L'objet entité est-il disponible dans $ context? Sinon, il peut se trouver quelque part dans $ form_state.

Une fois que vous avez obtenu l'entité Paragraphe, vous pouvez obtenir son parent en utilisant Paragraph::getParentEntity() et à partir de là le type du parent.

0
adrum99