Wie kann ich Elemente aus der Liste der zulässigen Werte eines Auswahlfelds entfernen, das Daten für die Werte enthält?


16

Ich habe einen Inhaltstyp mit einem Listen- / Auswahloptionsfeld erstellt und die Schlüssel / Wert-Paare eingegeben, die für die Funktion der Auswahlliste erforderlich sind.

Es wurden Daten eingegeben, und es wurde entschieden, dass bestimmte Begriffe nicht mehr gelten und dass sie gelöscht werden sollten.

Beim Versuch, diese Begriffe zu entfernen, wird jedoch der folgende Fehler angezeigt:

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

Offensichtlich werden sich im Leben eines Projekts die Werte ändern. Was ist eine praktische Möglichkeit, um Elemente zu entfernen, wenn den aufgelisteten Begriffen Knoten zugeordnet sind?

Dies ist ungefähr das Nächste, was ich finden konnte:

https://drupal.org/node/1653012

Es verweist auf ein d6-Plugin und einige Patch-Tricks, auf die ich lieber nicht zurückgreifen müsste. Wenn ich letztendlich auf den Patch zurückgreifen musste, um die Validierungsprüfung für dieses Feld zu entfernen, kann es dann schaden, diese Elemente auf den Knoten, mit denen sie verknüpft waren, verwaist zu lassen?

Update, ich bin wieder mit einem Regierungskunden auf dieses Problem gestoßen, der in den letzten 7 Jahren, als er eine Drupal-Site hatte, 50 Bundesstaaten und Gebiete in einer Auswahlliste hatte. Jetzt hat sich die Politik geändert und die Gebiete mussten nicht mehr einbezogen werden. Es ist wichtig, Gegenstände aus den Auswahllisten entfernen zu können, und daher biete ich ein Kopfgeld an.

Ich suche nach einer sicheren Lösung, um Elemente aus einer Auswahlliste entfernen zu können. Was ich nicht weiß, ist, ob diese Lösung einen der Knoten aktualisieren sollte, da ich nicht sicher bin, wie die Feldwerte im Verhältnis zum Gesamtinhalt eines Knotens gespeichert werden.

Ich bin mit einer reinen SQL-Lösung für MySQL zufrieden. oder ich suche ein Modul.


3
Offensichtlich werden sich im Leben eines Projekts die Werte ändern. Ich würde das bestreiten - Werte für eine statische Auswahlliste sollten zu Beginn des Projekts definiert werden. Wenn Sie Flexibilität benötigen, sollten Sie anstelle einer statischen Liste eine Termreferenz verwenden. Statische Listen beziehen sich auf Dinge wie Geschlecht (männlich / weiblich), die sich wahrscheinlich nicht so schnell ändern werden, es sei denn, wir haben eine ernsthafte Veränderung der Dinge. Andernfalls wird es hinzugefügt und nicht entfernt . Wann immer ich diesen 'Fehler' gemacht habe, habe ich immer herausgefunden, dass der beste Weg ist, manuell Daten
Clive

1
Möchten Sie diese Liste dynamisch gestalten? beim Erstellen und Löschen dynamisch sein.
M ama D

1
Ja, ich denke, das hängt von der damaligen Meinung ab - der Autohersteller wäre immer ein Knotentyp oder ein Vokabular für jede Site, die ich bauen würde. Da der Hersteller eine Fahrzeugkategorie ist (oder eine Fahrzeugkategorie, die von jemandem repariert wird), ist dies für mich als Taxonomie und nicht als Inhaltstyp am sinnvollsten. Aber ich weiß, dass das nicht hilft ... Ich wäre vorsichtig, wenn ich verwaiste Daten in der Datenbank belassen würde. Es ist sehr schwer zu sagen, welchen Effekt dies haben könnte, ohne genau zu wissen, was auf Ihrer Site installiert ist und wie es konfiguriert ist
Clive

1
Was ist los mit views_bulk_operations?
donquixote

1
heh, noch keine dieser Antworten hat eine positive Bewertung: /
tenken

Antworten:


7

Ich habe so etwas kürzlich mit dem folgenden Ansatz gemacht.

  1. Fügen Sie die neuen zulässigen Werte hinzu.
  2. Fügen Sie eine Einstellung hinzu, um "aktive" Werte zu konfigurieren.
  3. Filtern Sie die "inaktiven" Werte aus der Anzeige im Formular heraus.

z.B:

/**
 * 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]);
      }
    }
  }

}

Auf diese Weise bleiben die alten Daten als Referenz erhalten, das Formular wird validiert und die Datenintegrität bleibt erhalten.


1
Diese Option ist im Wesentlichen nicht destruktiv (dh, sie dient zum Ausblenden und nicht zum Löschen) und ist wahrscheinlich der beste Ausgangspunkt, bis Sie die beste Vorgehensweise für den Umgang mit Entitäten mit veralteten Optionen ermitteln können.
mpdonadio

3

Wie ich weiß, werden alle Felddaten in 2 Tabellen gespeichert: field_data_field_FIELDNAME und field_revision_field_FIELDNAME. Und ich fand hier eine Bestätigung meines Gedankens: /programming//a/7773117/1300562

Um unnötige Feldwerte zu entfernen, müssen Sie diese Werte aus den oben genannten Tabellen löschen und sie dann aus der Liste der zulässigen Werte entfernen.

Schritt 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();

Schritt 2.
Entfernen Sie unnötige Schlüsselpaare auf der Seite mit den Feldeinstellungen und senden Sie das Formular, um die Änderungen zu speichern.
Der Cache sollte danach automatisch geleert werden. Wenn Sie jedoch weiterhin entfernte Feldwerte auf Knotenseiten sehen, löschen Sie den Cache manuell.

PS Vor kurzem hatte ich ein ähnliches Problem und jetzt bevorzuge ich die Verwendung von Feldern vom Typ "Term reference" oder (noch besser) "Entity reference" anstelle einer Liste von Textwerten. Wenn Sie ein Referenzfeld verwenden, können Sie für jedes Feld ein eigenes Vokabular erstellen und Begriffe jederzeit einfach erstellen / bearbeiten / löschen.


Wenn sich das Feld wiederholt, werden bei diesen Abfragen die Deltas für die verbleibenden Daten nicht angepasst.
mpdonadio

1

Prüfen Sie zunächst, ob Sie im Feld zulässige Werte angegeben haben. Wenn Sie dies tun, wird eine andere Option nicht validiert. Versuchen Sie also zunächst, die Werte von der Registerkarte Feldeinstellungen zu entfernen.

Alternativ haben Sie 2 Möglichkeiten:


1.

Entfernen Sie alle Werte aus der Liste der zulässigen Werte, die von Benutzerkonten verwendet werden. Beispielsweise können Sie eine SQL-Abfrage ausführen, um diese zu finden:

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

oder erstellen Sie eine Benutzeransicht, in der angezeigt wird, welche Benutzerkonten den Wert haben, den Sie aus der Liste der zulässigen Werte entfernen möchten.


2.

Wenn Sie keine Werte aus den Feldern entfernen möchten, kann dies durch Hacken erreicht werden.

Achtung, dies ist keine empfohlene Lösung für die Produktion und Sie sollten wissen, was Sie tun!

  1. Suchen und bearbeiten Sie modules / field / field.module
  2. Suchen Sie die Funktion field_has_data () und fügen Sie sie return TRUE;in der ersten Funktionszeile hinzu.

    function field_has_data($field) {
      return FALSE; // HACK !!!
      $query = new EntityFieldQuery();
  3. Speichern Sie das Feld mit den gewünschten Werten erneut.
  4. Entfernen Sie den Hack, sobald Sie das tun.

0

Ich denke, Sie können dies tatsächlich mithilfe des Moduls " Views Bulk Operations" tun .

  1. Fügen Sie eine neue Option in das Feld ein, das Sie ersetzen möchten. Zum Beispiel: na | NA
  2. Erstellen Sie einen View to List-Knoten mit diesem Feld
  3. Fügen Sie in dieser Ansicht die Felder "Massenoperationen: Inhalt" hinzu
  4. Aktivieren Sie "Entitätswerte ändern" und "Verfügbare Token anzeigen" (wählen Sie "Alle anzeigen").
  5. Fügen Sie das Feld hinzu, das Sie in den Filterkriterien ändern möchten, und "machen" Sie diese Filter verfügbar
  6. Legen Sie den URL-Pfad für diese Ansicht fest
  7. Gehen Sie zu dieser Ansichtsseite und ändern Sie sie
  8. Verwenden Sie jetzt die Funktionen "Aussetzen" und "Operationen", um die Feldoption zu ändern
  9. Erledigt

0

Hier kommt eine Verbesserung für die HL-Antwort, die ich für die beste halte:

Zusammenfassend müssen Sie dem Inhalt, dem "alte" Werte für Ihr Auswahlfeld zugewiesen wurden, neue Werte zuweisen.

Abgesehen von Views-Massenvorgängen müssen Sie das Modul " Administrationsansichten" installieren und aktivieren . Mit diesem Modul haben Sie bereits eine sofort einsatzbereite Ansicht mit aktivierten Bulk-Vorgängen (sehen Sie einfach admin / content, sobald diese aktiviert sind). Dann:

1) Gehen Sie zu admin / structure / views und bearbeiten Sie die Ansicht "Administration: Node"

2) Fügen Sie über die Schaltfläche "Hinzufügen -> Seite" eine neue Seitenanzeige für die Ansicht hinzu

3) Ordnen Sie der neuen Anzeige einen Pfad zu: Beispiel admin / content / custom

4) Fügen Sie einen neuen Filter für Ihr Auswahlfeld hinzu: Wählen Sie den Operator "ist einer von" und wählen Sie dann alle Optionen aus, die Sie löschen möchten

5) Speichern Sie die Ansicht

6) Gehen Sie zu admin / content / custom. Jetzt sehen Sie alle Inhalte, die Sie für die Massenbearbeitung benötigen (ändern Sie den Wert für Ihr Auswahlfeld).

7) Wählen Sie alle Zeilen aus, indem Sie auf das erste Kontrollkästchen links in der Tabelle klicken. (Wenn es mehr als eine Seite gibt, wählen Sie auch eine Schaltfläche mit der Aufschrift "Alle X Zeilen in dieser Ansicht auswählen".)

8) Wählen Sie die Operation "Wert ändern" und drücken Sie "Ausführen"

9) Wählen Sie für Ihr Auswahlfeld einen neuen Wert aus, um die zu löschenden Werte zu überschreiben

10) Aktivieren Sie das Kontrollkästchen für dieses Auswahlfeld

11) Klicken Sie auf Weiter und Sie sind fertig


0

Es hört sich so an, als ob Ihr Drupal-Problem auf einem tieferen Datenproblem basiert: Was passiert mit den Entitäten, die derzeit die abgeschriebenen Listenwerte verwenden? Diese Frage ist die Wurzel der Fehlermeldung, die Drupal Ihnen sendet.

Schauen wir uns das Beispiel für Ihr Bundesland genauer an. Ihr Kunde verwendet seit Jahren ein System, das Staaten und Gebiete gleich behandelt, und hat eine große Gruppe von Knoten aufgebaut, die sowohl Staaten als auch Gebiete enthalten. Dann entscheiden eines Tages die Befugnisse darüber, dass Gebiete unterschiedlich behandelt werden müssen und dass das Dropdown-Menü für die Zuordnung von Regionen keine Gebiete mehr enthalten sollte. Groß. Erstellen Sie einfach eine Ansicht, die Standardfilter verwendet, um eine Liste aller Gebietsknoten zu rendern, und verwenden Sie Ansichts-Massenoperationen, um alle Regionswerte in ... was ... einen 51. Status zu ändern, der vielleicht als "anderer" bezeichnet wird. Das Schicksal der Gebiete ist eine sehr ernste Frage. Ihre Lösung muss eine Methode zum Beibehalten oder Verschieben des Gebietsstatus enthalten. Möglicherweise müssen Sie ein neues Listenfeld mit dem Namen "Gebiet" erstellen.

Sie müssen Regeln mit Massenvorgängen anzeigen verwenden, um diese Änderungen durchzuführen. Wenn Sie nicht viel über Regeln wissen, nehmen Sie sich bitte etwas Zeit, um zu erfahren, wie diese funktionieren. Mithilfe von Regeln können Sie Informationen basierend auf Auslösern, Bedingungen und Aktionen bearbeiten. Nachdem Sie die Regeln kennengelernt haben, stellen Sie möglicherweise fest, dass sich die gesuchten Antworten intuitiv selbst darstellen. Grundsätzlich müssen Sie eine Regel erstellen, die von einer Massenoperation ausgelöst wird und auf alle Gebiete abzielt und diese vom Hauptinformationsbestand entfernt, neu zuweist, umbenennt oder auf andere Weise trennt. Die Regel muss in der Lage sein, den Gebietsstatus auf irgendeine Weise zu speichern, während gleichzeitig die Status-Dropdown-Liste auf "Andere" oder "Nicht zutreffend" gesetzt wird. Dies kann alles sein, was benötigt wird. Andernfalls...

Nach der Neuzuweisung sollte es ein einfacher Vorgang sein, das ursprüngliche Listenfeld zu ändern und die Gebietsnamen zu entfernen. Wenn Sie die Liste jedoch immer noch nicht ändern können, müssen Sie möglicherweise ein neues Listenfeld erstellen. Überprüfen Sie dann mithilfe der Massenoperation und -regeln für Ansichten alle aktuellen Statuswerte und weisen Sie sie der neuen Liste zu. Regeln können mit Views-Massenoperationen zusammenarbeiten, um alle relevanten Knoten als Ziel festzulegen und basierend auf den Feldwerten auf diese zu reagieren. Das Festlegen des Werts eines neuen Listenfelds basierend auf dem Wert eines vorhandenen Listenfelds für eine Gruppe von Knoten ist einfach, wenn Sie Regeln verwenden.

Denken Sie auch daran, dass Sie bei Problemen mit Drupal immer den Cache leeren müssen, bevor Sie eine schwierige Alternative in Betracht ziehen.


0

Ich gehe davon aus, dass Ihr Kunde möchte, dass ältere Inhalte ihren ursprünglichen Wert beibehalten, dh, durch Ändern der Auswahlliste werden alle vorherigen Daten effektiv zerstört. Wenn das kein Problem ist, würde wahrscheinlich eine der anderen Antworten funktionieren. Wenn dies jedoch der Fall ist, können Sie die Auswahlliste nicht wirklich ändern, ohne den Datenverlauf zu verlieren. Möglicherweise gehe ich einen viel einfacheren Weg, um historische Daten zu berücksichtigen und gleichzeitig die Website ein wenig zukunftssicherer zu machen - ich würde vorschlagen, Feldberechtigungen zu verwenden:

* Richten Sie ein neues Feld für diese Auswahlliste ein, indem Sie eine Taxonomie anstelle statischer Daten verwenden

* Setzen Sie die Feldberechtigung für die vorhandene Auswahlliste auf VIEW, aber nicht auf EDIT von einer anderen Person als admin

Damit sollte das alte Feld sichtbar und durchsuchbar bleiben (fügen Sie einen neuen Titel hinzu, der es nur als Legacy darstellt), aber nicht bearbeitbar sein. Dies hängt natürlich stark von benutzerdefinierten Suchen, Ansichten usw. ab, die möglicherweise angepasst werden müssen.

Ich schlage dies vor (so chaotisch es auch klingen mag), weil das Entfernen dieser Daten, das Entfernen des Verlaufs und das Ende auf lange Sicht verheerend sein können. Sie können sogar css verwenden, um das alte Feld im Bearbeitungsknoten auszublenden, und einen Haken, um es für neuen Inhalt auszublenden (für den kein Wert festgelegt ist). Auf diese Weise würde es nur für diesen Altinhalt angezeigt.

Natürlich können Sie mit einem benutzerdefinierten Einzelmodul noch einen Schritt weiter gehen, um die Daten aus der alten Auswahlliste in die neue Taxonomie zu kopieren.


0

Ein einfaches Drush-Skript zur Rettung! Wir aktualisieren die Felddaten und Feldrevisionstabellen und ersetzen die alten Werte durch neue, bevor wir die Feldeinstellungen manuell ändern.

Wenn wir so etwas in unseren aktuellen Feldeinstellungen haben:

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

und möchten es durch Folgendes ersetzen:

date=today|today
date=last2days|last2days

Wir führen zuerst das Drush-Skript aus und ändern dann die Feldeinstellungen in der Admin-Benutzeroberfläche.

Hinweis: Dieser Code bezieht sich auf ein Feld mit einem Computernamen 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;
}

0

Ich habe den 2. Vorschlag von Kenorb verwendet und die Liste der Werte in einem Feld von Drupal 7.52, Profile2 7.x-1.3 aktualisiert. Wenn Sie also die Drupal-Warnung erhalten haben: "Liste der zulässigen Werte: Einige Werte werden gerade entfernt." Mit der folgenden Option konnte ich Werte aus dem Feld (profile2) entfernen, ohne sie in der Datenbank zu entfernen oder zu ersetzen.

Im Stammverzeichnis von Drupal Core befindet sich ein Ordner namens modules. Die zu bearbeitende Datei befindet sich unter modules / field / field.module. DIES IST EINE KERNDATEI. Sie müssen Ihre Änderungen unbedingt rückgängig machen, wenn Sie die Werte aktualisiert haben. Ich habe die Site offline geschaltet und vorübergehend den folgenden Codeblock in (Drupal-Stamm) /modules/field/field.module ersetzt

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();
}

MIT GENAU

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

Und Drupal hörte auf, sich zu beschweren, und ich konnte die Liste ändern. (In meinem Fall ist es eine Fakultät in der Liste der Werte, die die Universität verlassen haben, aber immer noch mit einer Studentenakte als Berater, Mentor usw. verknüpft sind.)

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.