Comment puis-je supprimer des éléments de la liste des valeurs autorisées d'un champ de sélection contenant des données pour les valeurs?

16

J'ai créé un type de contenu qui a un champ d'option liste / sélection, et j'ai entré les paires clé / valeur nécessaires pour que la liste de sélection fonctionne.

Des données ont été saisies et il a été décidé que certaines conditions ne s'appliquent plus et qu'elles devraient être supprimées.

Cependant, lorsque j'essaie de supprimer lesdits termes, j'obtiens l'erreur suivante:

Allowed values list: some values are being removed while currently in use.

Évidemment, dans la vie d'un projet, les valeurs vont changer. Quelle est la manière pratique de supprimer des éléments une fois que les nœuds sont associés aux termes répertoriés?

Il s'agit de la chose la plus proche que j'ai pu trouver:

https://drupal.org/node/1653012

Il fait référence à un plugin d6 et à une supercherie de patchs que je préférerais ne pas avoir à utiliser. Si je devais finalement utiliser le correctif pour supprimer la vérification de validation sur ce champ, y a-t-il un inconvénient à laisser ces éléments orphelins sur les nœuds auxquels ils étaient associés?

Mise à jour, je suis de nouveau tombé sur ce problème avec un client gouvernemental qui, au cours des 7 dernières années d'avoir un site Drupal, avait 50 États et territoires dans une liste sélective. Maintenant, la politique a changé et les territoires n'avaient plus besoin d'être inclus. Il est important de pouvoir supprimer des éléments des listes de sélection, et je propose donc une prime.

Je recherche une solution sûre pour pouvoir supprimer des éléments d'une liste de sélection. Ce que je ne sais pas, c'est si cette solution doit mettre à jour l'un des nœuds, car je ne sais pas comment les valeurs de champ sont stockées par rapport au contenu total d'un nœud.

Je suis satisfait d'une solution SQL pure à exécuter dans MySQL; ou, je cherche un module.

blue928
la source
3
Évidemment, dans la vie d'un projet, les valeurs vont changer. Je contesterais que - les valeurs d'une liste de sélection statique devraient être définies au début du projet. Si vous en avez besoin pour être flexible, vous devez utiliser une référence de terme au lieu d'une liste statique. Les listes statiques sont pour des choses comme le sexe (masculin / féminin) qui, à moins que nous ayons un changement sérieux dans les choses, ne devrait pas changer de sitôt. Et si c'est le cas, il sera ajouté à, pas supprimé . Chaque fois que j'ai fait cette «erreur», j'ai toujours trouvé que le meilleur moyen de revenir en arrière était d'exécuter des requêtes manuelles sur les données
Clive
1
Voulez-vous rendre cette liste dynamique? être dynamique dans la création et la suppression.
M ama D
1
Ouais, je suppose que ce n'est qu'une question d'opinion - le constructeur automobile serait toujours un type de nœud ou un vocabulaire pour n'importe quel site que je créerais. Étant donné que le constructeur est une catégorie de voiture (ou une catégorie de voiture que quelqu'un répare), cela me semble plus logique en tant que taxonomie plutôt qu'en tant que type de contenu. Mais je sais que cela n'aide pas ... Je me méfierais de laisser des données orphelines dans la base de données, il est très difficile de dire quel effet cela pourrait avoir sans savoir exactement ce qui est installé sur votre site et comment il est configuré
Clive
1
Quel est le problème avec views_bulk_operations?
donquixote
1
heh, aucune de ces réponses n'a encore de votes positifs: /
tenken

Réponses:

7

J'ai fait quelque chose comme ça récemment avec l'approche suivante.

  1. Ajoutez les nouvelles valeurs autorisées.
  2. Ajoutez un paramètre pour configurer les valeurs "actives".
  3. Filtrez les valeurs "inactives" de l'affichage sur le formulaire.

par exemple:

/**
 * Admin settings form
 */
function MODULE_admin_settings(){

  $form = array();

  // Select active preferences for display
  $field = field_info_field('field_preferences');
  $preferences = list_allowed_values($field);
  $form['field_preferences_active'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Active preferences'),
    '#options' => $preferences,
    '#description' => t('Select the preferences available for user selection.'),
    '#default_value' => variable_get('field_preferences_active', array()),
  );

  return system_settings_form($form);

}

/**
 * Implements hook_field_attach_form
 */
function MODULE_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) {

  // Filter out inactive preferences
  if(isset($form['field_preferences'])){
    $preferences = variable_get('field_preferences_active', array());
    foreach($preferences as $key => $preference){
      // If this preference isn't checked, but is set in the field values, unset it.
      if(empty($preference) && isset($form['field_preferences'][LANGUAGE_NONE]['#options'][$key])){
        unset($form['field_preferences'][LANGUAGE_NONE]['#options'][$key]);
      }
    }
  }

}

De cette façon, les données héritées sont préservées pour référence, le formulaire est validé et l'intégrité des données est intacte.

David Thomas
la source
1
Cette option est essentiellement non destructive (c.-à-d., Masquer des éléments plutôt que supprimer), et est probablement le meilleur point de départ jusqu'à ce que vous puissiez déterminer la meilleure ligne de conduite pour savoir comment traiter avec les entités qui ont les options obsolètes.
mpdonadio
3

Comme je le sais, toutes les données de champs sont stockées dans 2 tables: field_data_field_FIELDNAME et field_revision_field_FIELDNAME. Et j'ai trouvé la confirmation de ma pensée ici: /programming//a/7773117/1300562

Ainsi, pour supprimer les valeurs de champ inutiles, vous devez supprimer ces valeurs des tables susmentionnées, puis les supprimer de la liste des valeurs autorisées.

Étape 1.

$values_to_remove = array('value1', 'value2'); // an array of unnecessary values
$fieldname = 'FIELDNAME'; // name of your field. For example,
                          // 'territory' for field with machine name 'field_territory'
$entity_type = 'node'; // it's 'node' in your case, but it can be 'taxonomy_term' or something else

db_delete('field_data_field_' . $fieldname)
  ->condition('entity_type', $entity_type)
  ->condition('field_' . $fieldname . '_value', $values_to_remove)
  ->execute();

db_delete('field_revision_field_' . $fieldname)
  ->condition('entity_type', $entity_type)
  ->condition('field_' . $fieldname . '_value', $values_to_remove)
  ->execute();

Étape 2.
Supprimez les paires de clés inutiles sur la page des paramètres de champ et soumettez le formulaire pour enregistrer les modifications.
Le cache doit être effacé automatiquement après cela, mais si vous pouvez toujours voir les valeurs de champ supprimées sur les pages de noeud, videz le cache manuellement.

PS Récemment, j'ai rencontré un problème similaire, et maintenant je préfère utiliser des champs de type "Référence de terme" ou (encore mieux) "Référence d'entité" au lieu d'une liste de valeurs de texte. Lorsque vous utilisez un champ de référence, vous pouvez créer un vocabulaire distinct pour chaque champ et simplement créer / modifier / supprimer des termes à tout moment.

quotesBro
la source
Si le champ se répète, ces requêtes n'ajusteront pas les deltas pour les données restantes.
mpdonadio
1

Tout d'abord, vérifiez si vous avez des valeurs autorisées spécifiées dans le champ? Si vous le faites, une autre option ne sera pas validée. Essayez donc de supprimer d'abord les valeurs de l'onglet Paramètres de champ.

Alternativement, vous avez 2 options:


1.

Supprimez toutes les valeurs que vous avez placées dans la liste des valeurs autorisées qui sont utilisées par les comptes d'utilisateurs. Par exemple, vous pouvez exécuter une requête SQL pour les trouver:

SELECT * FROM field_data_field_MYFIELDNAME WHERE entity_type = 'user' and value = 'MY VALUE'

ou créez une vue utilisateur qui vous indique quels comptes d'utilisateurs ont la valeur que vous souhaitez supprimer de la liste des valeurs autorisées.


2.

Si vous ne souhaitez pas supprimer les valeurs des champs, cela peut être réalisé par piratage.

Attention, ce n'est pas une solution suggérée pour la production et vous devez savoir ce que vous faites!

  1. Rechercher et modifier des modules / champ / champ.module
  2. Recherchez la fonction field_has_data () et ajoutez return TRUE;la première ligne de la fonction.

    function field_has_data($field) {
      return FALSE; // HACK !!!
      $query = new EntityFieldQuery();
  3. Enregistrez à nouveau le champ avec les valeurs souhaitées.
  4. Supprimez le hack dès que vous faites cela.
Kenorb
la source
0

Je pense que vous pouvez réellement le faire en utilisant le module Views Bulk Operations .

  1. ajoutez une nouvelle option sur ce champ que vous souhaitez remplacer. par exemple: na | NA
  2. créer un noeud View to list contenant avec ce champ
  3. ajouter des champs "Opérations en bloc: Contenu" sur cette vue
  4. cochez "Modifier les valeurs d'entité" et "afficher les jetons disponibles" (sélectionnez Tout sur les valeurs d'affichage)
  5. Ajoutez le champ que vous souhaitez modifier sur les critères de filtrage et "exposez" les filtres
  6. définir le chemin de l'url sur cette vue
  7. Accédez à cette page d'affichage et modifiez
  8. Maintenant, utilisez les fonctionnalités d'expositions et d'opérations pour modifier l'option de champ
  9. Terminé
CocoSkin
la source
0

Voici une amélioration pour la réponse HL qui, je pense, est la meilleure:

Pour résumer, vous devez attribuer de nouvelles valeurs au contenu auquel des "anciennes" valeurs ont été attribuées pour votre champ de sélection.

En dehors de Views Bulk Operations , vous devrez installer et activer le module Administration Views . Avec ce module, vous avez déjà une vue prête à l'emploi avec des opérations en bloc activées (voir juste admin / content une fois activé). Alors:

1) Allez dans admin / structure / views et éditez la vue "Administration: Node"

2) Ajoutez un nouvel affichage de page pour la vue en utilisant le bouton "Ajouter -> Page" en haut

3) Attribuez un chemin au nouvel affichage: Exemple admin / content / custom

4) Ajoutez un nouveau filtre pour votre champ de sélection: Sélectionnez l'opérateur "fait partie de" puis sélectionnez toutes les options que vous souhaitez supprimer

5) Enregistrez la vue

6) Allez dans admin / content / custom Maintenant, vous voyez tout le contenu dont vous avez besoin pour modifier en masse (changer la valeur pour votre champ de sélection)

7) Sélectionnez toutes les lignes en cochant la première case à gauche du tableau (s'il y a plus d'une page, sélectionnez également un bouton qui indiquera "Sélectionnez toutes les X lignes dans cette vue")

8) Sélectionnez l'opération "change value" et appuyez sur "Execute"

9) Pour votre champ de sélection, sélectionnez une nouvelle valeur pour remplacer celles que vous souhaitez supprimer

10) Cochez la case de ce champ de sélection

11) Cliquez sur Suivant et vous avez terminé

Roger
la source
0

Il semble que votre problème Drupal soit basé sur un problème de données plus profond: qu'advient-il des entités qui utilisent actuellement les valeurs de liste dépréciées? Cette question est à l'origine du message d'erreur que Drupal vous envoie.

Regardons de plus près votre exemple d'état / territoire. Votre client utilise un système qui traite les États et les territoires de la même manière depuis des années et a constitué un énorme groupe de nœuds contenant à la fois des États et des territoires. Puis un jour, les pouvoirs en place décideront que les territoires doivent être traités différemment et que la liste déroulante pour attribuer une région ne devrait plus contenir de territoires. Génial. Créez simplement une vue qui utilise des filtres standard pour afficher une liste de tous les nœuds de territoire et utilisez Vues Opérations en bloc pour modifier toutes les valeurs de leur région en ... quoi ... un 51e état appelé peut-être autre? Le sort des territoires est une question très sérieuse. Votre solution doit inclure une méthode de préservation ou de relocalisation du statut de territoire. Vous devrez peut-être créer un nouveau champ de liste appelé «Territoire»

Vous devrez utiliser des règles avec View Bulk Operations pour effectuer ces modifications. Si vous ne savez pas grand-chose sur les règles, veuillez prendre le temps de vous renseigner sur leur fonctionnement. Les règles vous permettent de manipuler des informations en fonction des déclencheurs, des conditions et des actions. Après avoir appris les règles, vous constaterez peut-être que les réponses que vous cherchez se présenteront intuitivement. Fondamentalement, vous devrez créer une règle, déclenchée par une opération en bloc, qui ciblera tous les territoires et les supprimera, les réaffectera, les renommera ou les séparera du corps principal d'informations. La règle doit être en mesure de stocker l'état du territoire d'une manière ou d'une autre tout en définissant le menu déroulant de l'état sur le statut «autre» ou «N / A». C'est peut-être tout ce qui est nécessaire. Autrement...

Une fois la réaffectation effectuée, il devrait être simple de modifier le champ de liste d'origine et de supprimer les noms de territoire. Toutefois, si le système ne vous autorise toujours pas à modifier la liste, vous devrez peut-être créer un nouveau champ de liste, puis utiliser Vues Bulk Operation and Rules pour examiner toutes les valeurs d'état actuelles et les réaffecter à la nouvelle liste. Les règles peuvent fonctionner avec Views Bulk Operations pour cibler tous les nœuds pertinents et agir sur eux en fonction des valeurs de champ. Il est facile de définir la valeur d'un nouveau champ de liste en fonction de la valeur d'un champ de liste existant pour un groupe de nœuds lorsque vous utilisez des règles.

Rappelez-vous également que si Drupal vous pose problème lors d'une opération, videz toujours le cache avant d'envisager une alternative difficile.

Hoytman
la source
0

Je suppose que votre client souhaite que le contenu hérité conserve sa valeur d'origine, ce qui signifie que la modification de la liste de sélection détruira efficacement toutes les données précédentes. Si ce n'est pas un problème, alors l'une des autres réponses fonctionnerait probablement. Si tel est le cas, vous ne pouvez pas vraiment modifier la liste de sélection sans perdre cet historique de données. Je pourrais emprunter une voie beaucoup plus simple, pour permettre les données historiques, tout en rendant le site un peu plus à l'épreuve du temps - je suggérerais d'utiliser les autorisations de champ:

* configurer un nouveau champ pour cette liste de sélection en utilisant une taxonomie au lieu de données statiques

* définissez l'autorisation de champ pour la liste de sélection existante sur VIEW, mais pas EDIT par quiconque sauf l'administrateur

Avec cela, l'ancien champ doit rester visible et consultable (ajouter un nouveau titre le reflétant uniquement comme hérité) mais pas modifiable. Bien sûr, cela dépend fortement des recherches personnalisées, des vues, etc. qui peuvent avoir besoin d'être ajustées.

Je suggère cela (aussi désordonné que cela puisse paraître), car la suppression de ces données, supprime l'historique, et cela peut finir par être dévastateur à long terme. Vous pouvez même utiliser css pour masquer l'ancien champ dans le nœud d'édition et un crochet pour le masquer pour le nouveau contenu (où il n'a pas de valeur définie). De cette façon, cela ne s'afficherait que pour ce contenu hérité.

Bien sûr, vous pouvez ensuite aller plus loin avec un module personnalisé unique pour copier les données de l'ancienne liste de sélection vers la nouvelle taxonomie.

Geoff
la source
0

Un simple script de drush à la rescousse! Nous mettons à jour les données de champ et les tables de révision de champ et remplaçons les anciennes valeurs par de nouvelles avant de modifier manuellement les paramètres de champ.

Si nous avons quelque chose comme ça dans nos paramètres de champ actuels:

&date=today|today
&date=last2days|last2days

et souhaitez le remplacer par ce qui suit:

date=today|today
date=last2days|last2days

Nous exécutons d'abord le script drush, puis modifions les paramètres de champ dans l'interface utilisateur d'administration.

Remarque: Ce code est pour un champ avec le nom de la machine field_foo_bar.

    $field_name = 'foo_bar';

    print "for {$field_name}...\n";

    replace_field("&date=today", "date=today", $field_name);

    replace_field("&date=last2days", "date=last2days", $field_name);

    function replace_field($old_value, $new_value, $field_name, $entity_type='node') {
      print "Replacing {$old_value} with {$new_value}...\n";
      $data_count = replace_options_data_field($field_name, $entity_type, $old_value, $new_value);
      $revision_count = replace_options_revision_field($field_name, $entity_type, $old_value, $new_value);
      print $data_count + $revision_count . " entries replaced.\n";
    }

    function replace_options_data_field($field_name, $entity_type, $old_value, $new_value) {
      $num_updated = db_update('field_data_field_' . $field_name)
        ->fields(array(
                   'field_' . $field_name . '_value' => $new_value,
                 ))
        ->condition('entity_type', $entity_type)
        ->condition('field_' . $field_name . '_value', $old_value)
        ->execute();
      return $num_updated;
    }

function replace_options_revision_field($field_name, $entity_type, $old_value, $new_value) {
  $num_updated = db_update('field_revision_field_' . $field_name)
    ->fields(array(
               'field_' . $field_name . '_value' => $new_value,
             ))
    ->condition('entity_type', $entity_type)
    ->condition('field_' . $field_name . '_value', $old_value)
    ->execute();
  return $num_updated;
}
Badri
la source
0

J'ai utilisé la deuxième suggestion de kenorb et cela a fonctionné pour mettre à jour la liste des valeurs dans un champ Drupal 7.52, Profile2 7.x-1.3. Donc, si vous receviez l'avertissement drupal: «Liste des valeurs autorisées: certaines valeurs sont supprimées lorsqu'elles sont en cours d'utilisation». Ce qui suit m'a permis de supprimer des valeurs du champ (profile2), sans les supprimer ni les remplacer dans la base de données.

Dans le répertoire racine de Drupal core, il y a un dossier appelé modules, et le fichier à modifier se trouve à: modules / field / field.module. CECI EST UN FICHIER DE BASE, vous devez absolument annuler vos modifications lorsque vous avez mis à jour les valeurs. J'ai mis le site hors ligne, remplacé temporairement le bloc de code suivant dans (racine drupal) /modules/field/field.module

function field_has_data($field) {
  $query = new EntityFieldQuery();
  $query = $query->fieldCondition($field)
    ->range(0, 1)
    ->count()
    // Neutralize the 'entity_field_access' query tag added by
    // field_sql_storage_field_storage_query(). The result cannot depend on the
    // access grants of the current user.
    ->addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT');

  return (bool) $query
    ->execute() || (bool) $query
    ->age(FIELD_LOAD_REVISION)
    ->execute();
}

AVEC EXACTEMENT

function field_has_data($field) { 
    return FALSE; // hack 
    $query = new EntityFieldQuery();
}

Et Drupal a cessé de se plaindre et j'ai pu modifier la liste. (Dans mon cas, c'est la faculté dans la liste des valeurs qui ont quitté l'université, mais qui sont toujours associées à un dossier d'étudiant, comme conseiller, mentor, etc.)

Michael Martelle
la source