web-dev-qa-db-fra.com

Ajouter un champ de type de contenu par programme

Mon module fournit un formulaire de configuration qui permet de sélectionner un type de contenu et lors de la soumission, 2 nouveaux champs seront ajoutés aux types de contenu sélectionnés.

Je veux ajouter ces champs aux types de contenu par programme et j'ai essayé ceci en utilisant hook_entity_bundle_field_info mais les champs ne sont pas enregistrés.

Comment puis-je enregistrer les champs? Et comment puis-je supprimer les champs (si l'utilisateur modifie le type de contenu dans le formulaire de configuration)?

7
Kpone

Vous pouvez utiliser cet exemple à partir du module de noeud.

Cela ajoute un champ de corps lorsqu'un type de contenu est créé et configure en même temps les modes d'affichage (modes d'affichage et modes de formulaire):

core/modules/node/node.module:

/**
 * Adds the default body field to a node type.
 *
 * @param \Drupal\node\NodeTypeInterface $type
 *   A node type object.
 * @param string $label
 *   (optional) The label for the body instance.
 *
 * @return \Drupal\field\Entity\FieldConfig
 *   A Body field object.
 */
function node_add_body_field(NodeTypeInterface $type, $label = 'Body') {
  // Add or remove the body field, as needed.
  $field_storage = FieldStorageConfig::loadByName('node', 'body');
  $field = FieldConfig::loadByName('node', $type->id(), 'body');
  if (empty($field)) {
    $field = FieldConfig::create([
      'field_storage' => $field_storage,
      'bundle' => $type->id(),
      'label' => $label,
      'settings' => ['display_summary' => TRUE],
    ]);
    $field->save();

    /** @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface $display_repository */
    $display_repository = \Drupal::service('entity_display.repository');

    // Assign widget settings for the default form mode.
    $display_repository->getFormDisplay('node', $type->id())
      ->setComponent('body', [
        'type' => 'text_textarea_with_summary',
      ])
      ->save();

    // Assign display settings for the 'default' and 'teaser' view modes.
    $display_repository->getViewDisplay('node', $type->id())
      ->setComponent('body', [
        'label' => 'hidden',
        'type' => 'text_default',
      ])
      ->save();

    // The teaser view mode is created by the Standard profile and therefore
    // might not exist.
    $view_modes = \Drupal::service('entity_display.repository')->getViewModes('node');
    if (isset($view_modes['teaser'])) {
      $display_repository->getViewDisplay('node', $type->id(), 'teaser')
        ->setComponent('body', [
          'label' => 'hidden',
          'type' => 'text_summary_or_trimmed',
        ])
        ->save();
    }
  }

  return $field;
}

Edit: Code mis à jour à partir de 8.8.x pour supprimer les fonctions obsolètes, voir enregistrement des modifications https://www.drupal.org/node/ 2835616

Le stockage de champ lui-même n'est pas ajouté ou supprimé car il est partagé entre tous les types de contenu. Vous devez le faire une fois lorsque vous installez le module. Le moyen le plus simple consiste à placer un fichier yml pour le stockage dans/config/install. Exemple du module de noeud:

core/modules/node/config/install/field.storage.node.body.yml:

langcode: en
status: true
dependencies:
  module:
    - node
    - text
id: node.body
field_name: body
entity_type: node
type: text_with_summary
settings: {  }
module: text
locked: false
cardinality: 1
translatable: true
indexes: {  }
persist_with_no_fields: true
custom_storage: false
13
4k4

Edit : Little More Description: Pour ajouter par programme le type d'entité (type de contenu, type de bloc, type de produit, type de variation ...) dont vous avez besoin

  1. Créer une configuration de stockage sur le terrain : alors seulement
  2. Créer une configuration de champ

Vous pouvez utiliser Drupal 8 configuration Single export qui peut être trouvé ici -> /admin/config/development/configuration/single/export

La sélection nécessaire du stockage des champs ou de la configuration des champs vous donnera les champs souhaités et leur valeurs. enter image description here

Suivant Tout est très bien décrit

J'aime ajouter que le code des modules de nœuds utilise des fonctions obsolètes. (Nous sommes maintenant 8.5.6).

Voici ma partie du code qui gère "créer un stockage de champ par programme:

if (empty($fieldStorageMicrositesfield = \Drupal\field\Entity\FieldStorageConfig::loadByName('node', $fieldName))) {
  $fieldStorage = \Drupal\field\Entity\FieldStorageConfig::create(
    [
      'field_name'             => $fieldName,
      'langcode'               => 'en',
      'entity_type'            => 'node',
      'type'                   => 'list_string',
      'settings'               => [
        'allowed_values'          => [],
        'allowed_values_function' => 'I_used_a_custum_function_here_which_you_not_need_I_guess',
      ],
      'module'                 => 'options',
      'locked'                 => FALSE,
      'cardinality'            => -1,
      'translatable'           => TRUE,
      'persist_with_no_fields' => FALSE,
      'custom_storage'         => FALSE,
    ]
  );
  $fieldStorageSaved = $fieldStorage->save();
  if ($fieldStorageSaved) {
    $message = t(
      "Field @a storage created.",
      ['@a' => $fieldName,]
    );
  }
  else {
    $message = t(
      "Field @a storage could not be created.",
      ['@a' => $fieldName,]
    );
  }
}
else {
  $message = t(
    "Field @a storage could not be created because the field already exists",
    ['@a' => $fieldName,]
  );
}

Voici ma partie du code qui gère l'ajout d'un champ à plusieurs types de contenu après avoir créé le stockage ($bundles contient le tableau de mes types de contenu):

$entityTypemanager = \Drupal::entityTypeManager();

foreach ($bundles as $bundle) {
  $field = FieldConfig::loadByName('node', $bundle, $fieldName);
  if (empty($field)) {
    FieldConfig::create(
      [
        'field_name'   => $fieldName,
        'entity_type'  => 'node',
        'bundle'       => $bundle,
        'label'        => $label,
        'required'     => TRUE,
        'translatable' => TRUE,
        'description'  => t(
          $description
        ),
      ]
    )->save();
    $message .= "\n" . t(
        "Field @a created in bundle @b.",
        ['@a' => $fieldName, '@b' => $bundle]
      );

    // Assign widget settings for the 'default' form mode.
    $displayForm = $entityTypemanager
      ->getStorage('entity_form_display')
      ->load('node.' . $bundle . '.default')
      ->setComponent($fieldName, [
        'type'   => 'options_buttons',
        'weight' => 100,
      ]);
    $messagePart = '';
    if ($displayForm->save()) {
      $messagePart .= ' form-';
    }
    else {
      $message .= "\n" . t(
          "The form display of @a in bundle @b could not be set",
          ['@a' => $fieldName, '@b' => $bundle]
        );
    }
    unset($displayForm);

    // Assign display settings for the 'default' and 'teaser' view modes.
    $displayDefault = $entityTypemanager
      ->getStorage('entity_view_display')
      ->load('node.' . $bundle . '.default')
      ->removeComponent($fieldName);
    if ($displayDefault->save()) {
      $messagePart .= ' default-';
    }
    else {
      $message .= "\n" . t(
          "The default display of @a in bundle @b could not be set",
          ['@a' => $fieldName, '@b' => $bundle]
        );
    }
    unset($displayDefault);

    // The teaser view mode is created by the Standard profile and therefore
    // might not exist.
    $viewModes = \Drupal::service('entity_display.repository')
      ->getViewModes('node');
    if (isset($viewModes['teaser'])) {
      $displayTeaser = $entityTypemanager
        ->getStorage('entity_view_display')
        ->load('node.' . $bundle . '.teaser')
        ->removeComponent($fieldName);
      if ($displayTeaser->save()) {
        $messagePart .= ' teaser-';
      }
      else {
        $message .= "\n" . t(
            "The teaser display of @a in bundle @b could not be set",
            ['@a' => $fieldName, '@b' => $bundle]
          );
      }
      unset($displayTeaser);
    }
    $message .= "\n" . t(
        $messagePart . "Display(s) of @a in bundle @b are set.",
        ['@a' => $fieldName, '@b' => $bundle]
      );

  }
  else {
    $message .= "\n" . t(
        "Field @a already exists in bundle @b.",
        ['@a' => $fieldName, '@b' => $bundle]
      );
  }
}
7
Lars Jendrzejewski