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 correctifs que je préfère 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 à nouveau confronté à ce problème avec un client gouvernemental qui, au cours des 7 dernières années, ayant un site Drupal a eu 50 États et territoires dans une liste de sélection. 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.
J'ai fait quelque chose comme ça récemment avec l'approche suivante.
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.
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: https://stackoverflow.com/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 inutiles de clé | valeur 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.
P. S. 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 (mieux encore) "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.
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!
Recherchez la fonction field_has_data () et ajoutez return TRUE;
dans la première ligne de fonction.
function field_has_data($field) {
return FALSE; // HACK !!!
$query = new EntityFieldQuery();
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;
}
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 pendant leur 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 dans: modules/field/field.module. CECI IS 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.)
Je pense que vous pouvez réellement le faire en utilisant le module Views Bulk Operations .
Voici une amélioration pour la réponse H-L qui, je pense, est la meilleure:
Pour résumer, vous devez attribuer de nouvelles valeurs au contenu auquel des "anciennes" valeurs sont 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 cliquant sur 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 "changer la valeur" et appuyez sur "Exécuter"
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é
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.
Examinons 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 qui contiennent à 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 Views Bulk Operations pour modifier toutes les valeurs de leur région en ... quoi ... un 51e état appelé autre peut-être? 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" qui peut être utilisé pour identifier les zones qui sont des territoires, ou créer un type de données entièrement nouveau pour eux.
Vous devrez utiliser Rules with View Bulk Operations afin d'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 pouvez constater 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. Cependant, 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.
Souvenez-vous également que si Drupal vous pose problème lors d'une opération, videz toujours le cache avant d'envisager une alternative difficile.
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 aller plus loin avec un module unique personnalisé pour copier les données de l'ancienne liste de sélection vers la nouvelle taxonomie.