web-dev-qa-db-fra.com

Quelle est la manière appropriée de stocker des tableaux d'informations avec l'API de configuration?

Dans Drupal 7 avec des formulaires et des variables personnalisés, on pouvait facilement stocker des tableaux d'informations dans le tableau des "variables". Je construisais parfois des formulaires de configuration qui fournissaient un paramètre pour chaque rôle d'utilisateur. Ensuite, je pouvais stockez les paramètres de chaque rôle dans une variable distincte ou regroupez tous les paramètres dans une seule baie et stockez-les de cette façon.

Je me demande quelle est la meilleure méthode standard pour faire une chose similaire dans Drupal 8.

in Drupal 7 J'aurais quelque chose comme ça pour un code de formulaire:

// build list of roles
  $user_roles = user_roles(TRUE);
  // remove authenticated user role from options
  if (isset($user_roles[2])) {
    unset($user_roles[2]);
  }
$role_settings = variable_get('MYMODULE_role_type_mapping', $role_settings);
foreach ($user_roles as $rid => $role) {
      $form['roles']['other_roles']['MYMODULE_role_' . $rid . '_type_mapping'] = [
        '#title'         => $role,
        '#type'          => 'select',
        '#options'       => $membership_types,
        '#default_value' => !empty($role_settings[$rid]) ? $role_settings[$rid] : '',
      ];
    }

puis quelque chose comme ça dans le formulaire soumettre un rappel:

    // build list of roles
      $user_roles = user_roles(TRUE);
      // remove authenticated user role from options
      if (isset($user_roles[2])) {
        unset($user_roles[2]);
      }
      foreach ($user_roles as $rid => $role) {
        $role_settings[$rid] = !empty($form_state['values']['MYMODULE_role_' . $rid . '_type_mapping']) ? $form_state['values']['MYMODULE_role_' . $rid . '_type_mapping'] : '';
      }
variable_set('MYMODULE_role_type_mapping', $role_settings);

Ce type de chose est nécessaire lorsque vous installez le module personnalisé sur plusieurs sites, où il pourrait y avoir un nombre différent de rôles sur chaque site.

Donc maintenant avec Drupal 8 nous avons cette nouvelle API de configuration. Je ne peux pas supposer que je connais les rôles à l'avance.

J'espérais y parvenir avec "Simple Configuration" mais je me rends compte qu'il peut être nécessaire de créer une entité de configuration personnalisée, bien que si cela peut être fait sans cela, ce serait Nice et "simple".

Selon cette ressource: https://www.drupal.org/node/1905070#types Il n'y a que quelques types de schéma pour les champs de configuration, dont aucun ne semble intuitivement approprié à ce cas.

En lisant cette page, il n'est même pas évident de savoir comment on stockerait la valeur d'une liste de sélection à valeurs multiples dans la configuration, encore moins une variable qui pourrait être un tableau de toutes sortes d'informations différentes. En D7, une liste de sélection à plusieurs valeurs retournerait un tableau. En D7, les variables sont stockées en tant que variables sérialisées. Même "simple_settings_form" de D7 ne gèrerait cela sans aucun problème.

Certes, ce type de problème a été résolu à plusieurs reprises, mais il n'est pas "simple" de trouver des informations.

Le problème est donc double 1) Il suffit de stocker un tableau de valeurs dans la configuration, avec un nombre inconnu d'éléments de tableau, nombre dépendant des conditions de site personnalisées (comme les rôles d'utilisateur sur un site) 2) Déballer ce tableau et configurer des éléments de formulaire pour il, qui lors de la soumission, regroupe le tout dans une variable.

Question similaire, une question plus simple est: si l'on définit le schéma de configuration pour une liste de sélection à plusieurs valeurs, quel type de données utilise-t-on? Chaîne?

Est-ce que le modèle que j'ai utilisé ici pour D7 est même portable pour D8, il y a probablement un meilleur moyen d'aller sans doute, mais faire une entité de configuration pour chaque rôle dans le site et tout cela ne semble pas simple et certainement pas aussi simple que possible être fait en D7. Je veux donner une idée de la configuration de l'exportation/importation entre les sites. Les versions dev/staging/production du site peuvent toutes avoir les mêmes rôles d'utilisateur, mais certainement pas des sites Web complètement séparés.

Bien que je pose plusieurs questions dans cet article, le thème commun est de savoir comment stocker les tableaux d'informations en tant que configuration de manière appropriée dans Drupal 8? Le cas simple est la valeur d'une liste de sélection à plusieurs valeurs, plus complexe scénario du paramètre par rôle d'utilisateur comme je le décris.

Merci d'avance!

4
jackrabbithanna

Vous définissez un type de schéma sequence:

Exemple: /core/modules/options/config/schema/options.schema.yml

# Schema for the configuration files of the Options module.

field.storage_settings.list_integer:
  type: mapping
  label: 'List (integer) settings'
  mapping:
    allowed_values:
      type: sequence
      label: 'Allowed values list'
      sequence:
        type: mapping
        label: 'Allowed value with label'
        mapping:
          value:
            type: integer
            label: 'Value'
          label:
            type: label
            label: 'Label'

Vous trouverez le formulaire pour cet exemple dans /core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php

Plus d'informations https://www.drupal.org/docs/8/api/configuration-api/configuration-schemametadata

7
4k4

Je me débattais récemment sur la façon de stocker des données avec un tableau imbriqué de chaînes,

allowed_view_modes:
  image:
    embed: embed
    full: full

La seule façon dont je pouvais comprendre comment le valider était en exécutant des tests fonctionnels, où il valide les configurations lorsque vous enregistrez une entité de configuration.

J'ai pu enregistrer des données comme les données ci-dessus en imbriquant des "séquences":

ckeditor.plugin.drupalmedia:
  type: mapping
  label: 'Media Embed'
  mapping:
    allowed_view_modes:
      type: sequence
      label: 'Allowed View Modes'
      nullable: true
      sequence:
        type: sequence
        nullable: true
        label: 'View Mode'
        sequence:
          type: string

Cela a fonctionné et passé le linter de configuration.

La séquence de niveau supérieur est pour le type de support, la séquence interne est pour chaque mode d'affichage. Il y a beaucoup d'exemples complexes dans drupal core. Malheureusement, je ne sais pas où vous diriger pour la documentation. J'ai surtout appris cela par essais et erreurs.

2
oknate

C'était le plugin openid_connect personnalisé sur lequel je travaillais, donc un peu différent d'un formulaire de configuration normale ConfigFormBase, mais j'espère que cette méthodologie s'applique et sera utile à quelqu'un à l'avenir. J'ai utilisé un schéma comme ça (extrait):

# Schema for the configuration files of the OpenID Connect module.
openid_connect.settings.nimble:
  type: config_object
  label: 'OpenID Connect Nimble settings'
  mapping:
    enabled:
      type: boolean
      label: 'Enable client'
    settings:
      type: mapping
      mapping:
        roles_membership_types:
        type: sequence
        label: 'Role Membership Types'
        sequence:
          type: mapping
          label: 'Roles mapped to membership types'
          mapping:
            role:
              type: string
              label: 'Role id'
            membership_type:
              type: string
              label: 'Membership Type'

Configuration FAPI comme ceci (je n'avais AUCUN index de formulaire pour le nom réel de l'élément de configuration, roles_membership_types:

    $roles = user_role_names(TRUE);
    if (isset($roles['authenticated'])) {
      unset($roles['authenticated']);
    }
    $membership_types = ['' => 'None'] + $this->getMembershipTypes($this->configuration['instance']);
    $roles_membership_types = $this->configuration['roles_membership_types'];
    if (!empty($roles_membership_types)) {
      foreach ($roles_membership_types as $type) {
        $roles_membership_types_default_values[$type['role']] = $type['membership_type'];
      }
    }
    foreach ($roles as $rid => $role) {
      $form['roles_mapped_membership_types'][$rid] = [
        '#title'         => $role,
        '#type'          => 'select',
        '#options'       => $membership_types,
        '#default_value' => !empty($roles_membership_types_default_values[$rid]) ? $roles_membership_types_default_values[$rid] : '',
      ];
    }

Un peu de code dans le gestionnaire de soumission pour obtenir les valeurs des éléments du formulaire de rôle et les assembler au format nécessaire pour mapper la configuration.

$values = $form_state->getValues();
if (!empty($values['roles_mapped_membership_types'])) {
  foreach ($values['roles_mapped_membership_types'] as $rid => $membership_type) {
    $roles_to_membership_type_value[] = ['role' => $rid, 'membership_type' => $membership_type];
  }
$form_state->setValue('roles_membership_types', $roles_to_membership_type_value);
}

Donc, finalement, ce code fonctionnerait:

// Save plugin settings.
$this->configFactory()
  ->getEditable('openid_connect.settings.' . $plugin_id)
  ->set('settings', $subform_state->getValues())
  ->save();
2
jackrabbithanna