Jak mogę usunąć elementy z listy dozwolonych wartości pola wyboru, które zawiera dane dla wartości?


16

Stworzyłem typ zawartości, który ma pole listy / wyboru i wprowadziłem pary klucz | wartość, jeśli jest to konieczne, aby lista wyboru działała.

Dane zostały wprowadzone i zdecydowano, że niektóre warunki nie mają już zastosowania i że należy je usunąć.

Jednak podczas próby usunięcia wspomnianych warunków pojawia się następujący błąd:

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

Oczywiście w życiu projektu wartości się zmienią. Jaki jest praktyczny sposób usuwania elementów, gdy węzły zostaną powiązane z wymienionymi warunkami?

To jest najbliższa rzecz, jaką mogłem znaleźć:

https://drupal.org/node/1653012

Odwołuje się do wtyczki d6 i niektórych sztuczek, do których wolałbym się nie uciekać. Jeśli musiałem ostatecznie skorzystać z łatki w celu usunięcia kontroli sprawdzania poprawności w tym polu, czy pozostawienie tych elementów osieroconym w węzłach, z którymi były skojarzone, jest szkodliwe?

Aktualizacja, ponownie natknąłem się na ten problem z klientem rządowym, który przez ostatnie 7 lat posiadania witryny Drupal miał 50 stanów i terytoriów na wybranej liście. Teraz zasady się zmieniły i nie trzeba już uwzględniać terytoriów. Możliwość usuwania elementów z wybranych list jest ważna, dlatego oferuję nagrodę.

Szukam bezpiecznego rozwiązania, aby móc usunąć elementy z listy wyboru. Nie wiem, czy to rozwiązanie powinno zaktualizować dowolny z węzłów, ponieważ nie jestem pewien, jak przechowywane są wartości pól w stosunku do całkowitej zawartości węzła.

Jestem zadowolony z czystego rozwiązania SQL do uruchomienia w MySQL; lub szukam modułu.


3
Oczywiście w życiu projektu wartości się zmienią. Kwestionowałbym to - wartości dla statycznej listy wyboru powinny zostać określone na początku projektu. Jeśli potrzebujesz być elastyczny, powinieneś użyć odwołania do terminu zamiast statycznej listy. Listy statyczne dotyczą rzeczy takich jak seks (mężczyzna / kobieta), które, chyba że nastąpią poważne zmiany, prawdopodobnie nie zmienią się w najbliższym czasie. A jeśli tak, zostanie dodany , a nie usunięty . Ilekroć popełniłem ten „błąd”, zawsze znajdowałem najlepszy sposób, aby się wycofać, uruchamiając ręczne zapytania dotyczące danych
Clive

1
Czy chcesz, aby ta lista była dynamiczna? dynamiczny w tworzeniu i usuwaniu.
M am D

1
Tak, to chyba tylko opinia - producent samochodów zawsze będzie typem węzła lub słownictwem dla każdej strony, którą zbuduję. Ponieważ producent jest kategorią samochodu (lub kategorią samochodu, który ktoś naprawia), ma on dla mnie sens raczej taksonomię niż typ zawartości. Ale wiem, że to nie pomaga ... Byłbym ostrożny z pozostawieniem osieroconych danych w bazie danych, bardzo trudno jest powiedzieć, jaki efekt mógłby to mieć, nie wiedząc dokładnie, co jest zainstalowane na twojej stronie i jak jest skonfigurowany
Clive

1
Co jest nie tak z views_bulk_operations?
donquixote

1
heh, żadna z tych odpowiedzi nie ma jeszcze pozytywnych opinii: /
tenken

Odpowiedzi:


7

Ostatnio zrobiłem coś takiego, stosując następujące podejście.

  1. Dodaj nowe dozwolone wartości.
  2. Dodaj ustawienie, aby skonfigurować „aktywne” wartości.
  3. Odfiltruj „nieaktywne” wartości z wyświetlacza w formularzu.

na przykład:

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

}

W ten sposób starsze dane są zachowywane do wglądu, formularz jest sprawdzany, a integralność danych jest nienaruszona.


1
Ta opcja jest w zasadzie nieindywidualna (tzn. Raczej ukrywa rzeczy niż usuwa) i jest prawdopodobnie najlepszym punktem wyjścia, dopóki nie można określić najlepszego sposobu postępowania z jakimikolwiek podmiotami, które mają przestarzałe opcje.
mpdonadio

3

Jak wiem, wszystkie dane pól są przechowywane w 2 tabelach: field_data_field_FIELDNAME i field_revision_field_FIELDNAME. I znalazłem potwierdzenie mojej myśli tutaj: /programming//a/7773117/1300562

Aby usunąć niepotrzebne wartości pól, należy usunąć te wartości z wyżej wymienionych tabel, a następnie usunąć je z listy dozwolonych wartości.

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

Krok 2.
Usuń niepotrzebne pary klucz | wartość ze strony ustawień pola i prześlij formularz, aby zapisać zmiany.
Pamięć podręczna powinna zostać wyczyszczona automatycznie, ale jeśli nadal widzisz usunięte wartości pól na stronach węzłów, wyczyść pamięć podręczną ręcznie.

PS Ostatnio miałem do czynienia z podobnym problemem, a teraz wolę używać pól typu „Odwołanie do terminu” lub (jeszcze lepiej) „Odwołanie do jednostki” zamiast listy wartości tekstowych. Korzystając z pola referencyjnego, możesz utworzyć osobne słownictwo dla każdego pola i po prostu tworzyć / edytować / usuwać terminy w dowolnym momencie.


Jeśli pole się powtarza, zapytania te nie dostosują delt dla pozostałych danych.
mpdonadio

1

Przede wszystkim sprawdź, czy masz jakieś dozwolone wartości określone w polu? Jeśli to zrobisz, inna opcja nie zostanie sprawdzona. Spróbuj najpierw usunąć wartości z karty Ustawienia pola.

Alternatywnie masz 2 opcje:


1.

Usuń wszystkie wartości, które umieściłeś na liście dozwolonych wartości, które są używane przez konta użytkowników. Na przykład możesz uruchomić zapytanie SQL, aby je znaleźć:

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

lub utwórz widok użytkownika, który pokazuje, które konta użytkowników mają wartość, którą chcesz usunąć z listy dozwolonych wartości.


2)

Jeśli nie chcesz usuwać wartości z pól, możesz to zrobić poprzez hack.

Uwaga, nie jest to sugerowane rozwiązanie dla produkcji i powinieneś wiedzieć, co robisz!

  1. Znajdź i edytuj moduły / field / field.module
  2. Znajdź funkcję field_has_data () i dodaj return TRUE;w pierwszym wierszu funkcji.

    function field_has_data($field) {
      return FALSE; // HACK !!!
      $query = new EntityFieldQuery();
  3. Ponownie zapisz pole z żądanymi wartościami.
  4. Usuń hack, gdy tylko to zrobisz.

0

Myślę, że faktycznie możesz to zrobić za pomocą modułu Views Bulk Operations .

  1. dodaj nową opcję w polu, które chcesz zastąpić. na przykład: na | NA
  2. za pomocą tego pola utwórz węzeł Widok do listy zawierający
  3. dodaj pola „Operacje zbiorcze: treść” w tym widoku
  4. zaznacz „Modyfikuj wartości encji” i „pokaż dostępne tokeny” (wybierz Wszystkie na wyświetlanych wartościach)
  5. Dodaj pole, które chcesz zmienić, w polu Kryteria filtrowania i „ujawnij” to filtry
  6. ustaw ścieżkę adresu URL w tym widoku
  7. Przejdź do tej strony widoku i zmień
  8. Teraz użyj funkcji ujawnienia i operacji, aby zmienić opcję pola
  9. Gotowy

0

Oto poprawka dla odpowiedzi HL, która moim zdaniem jest najlepsza:

Podsumowując, musisz przypisać nowe wartości do treści, której „stare” wartości zostały przypisane do twojego pola wyboru.

Oprócz operacji widoku zbiorczego należy zainstalować i włączyć moduł Widoki administracyjne . Dzięki temu modułowi masz już gotowy widok z włączonymi operacjami zbiorczymi (po prostu zobacz admin / content po włączeniu). Następnie:

1) Przejdź do admin / structure / views i edytuj widok „Administration: Node”

2) Dodaj nową stronę do widoku za pomocą przycisku „Dodaj -> Strona” u góry

3) Przypisz ścieżkę do nowego ekranu: Przykład admin / content / custom

4) Dodaj nowy filtr do pola wyboru: Wybierz operator „jest jednym z”, a następnie wybierz wszystkie opcje, które chcesz usunąć

5) Zapisz widok

6) Idź do admin / content / custom Teraz zobaczysz całą zawartość, którą musisz edytować zbiorczo (zmień wartość dla wybranego pola)

7) Wybierz wszystkie wiersze, klikając pierwsze pole wyboru po lewej stronie tabeli (jeśli jest więcej niż jedna strona, wybierz również przycisk, który powie „Wybierz wszystkie X wierszy w tym widoku”)

8) Wybierz operację „zmień wartość” i naciśnij „Wykonaj”

9) W polu wyboru wybierz nową wartość, aby zastąpić te, które chcesz usunąć

10) Zaznacz pole wyboru dla tego pola wyboru

11) Kliknij przycisk Dalej i gotowe


0

Wygląda na to, że problem Drupala opiera się na głębszym problemie z danymi: co dzieje się z jednostkami, które obecnie używają zaniżonych wartości z listy? To pytanie leży u podstaw komunikatu o błędzie wysyłanego przez Drupala.

Przyjrzyjmy się bliżej przykładowi stanu / terytorium. Twój klient korzysta z systemu, który od lat traktuje stany i terytoria w taki sam sposób i stworzył ogromną grupę węzłów, które zawierają zarówno stany, jak i terytoria. Pewnego dnia moce decydują, że terytoria muszą być traktowane inaczej i że lista rozwijana dla przypisywania regionu nie powinna już zawierać terytoriów. Świetny. Po prostu utwórz widok, który używa standardowych filtrów do renderowania listy wszystkich węzłów terytorium, i użyj operacji Widok zbiorczy, aby zmienić wszystkie ich wartości regionu na ... co ... może jakiś 51 stan nazywa się innym? Losy terytoriów to bardzo poważne pytanie. Twoje rozwiązanie musi zawierać metodę zachowania lub przeniesienia statusu terytorium. Może być konieczne utworzenie nowego pola listy o nazwie „Terytorium”

Aby wprowadzić te zmiany, musisz użyć reguł z widokami operacji masowych . Jeśli nie wiesz dużo o regułach, poświęć trochę czasu, aby dowiedzieć się, jak one działają. Reguły umożliwiają manipulowanie informacjami na podstawie wyzwalaczy, warunków i działań. Po zapoznaniu się z regułami może się okazać, że odpowiedzi, których szukasz, intuicyjnie się przedstawią. Zasadniczo musisz utworzyć regułę uruchamianą przez operację zbiorczą, która będzie kierowana na wszystkie terytoria i usunie je, zmieni przydział, zmieni nazwę lub w inny sposób oddzieli je od głównej części informacji. Reguła musi być w stanie w jakiś sposób zapisać stan terytorium, a jednocześnie ustawić rozwijany stan na „inny” lub „nie dotyczy”. To może być wszystko, czego potrzeba. Inaczej...

Po zmianie przypisania zmiana pierwotnego pola listy i usunięcie nazw terytorium powinno być prostą operacją. Jeśli jednak system nadal nie pozwala na zmianę listy, konieczne może być utworzenie nowego pola listy, a następnie użycie operacji Widok zbiorczy i reguł, aby przejrzeć wszystkie bieżące wartości stanu i ponownie przypisać je do nowej listy. Reguły mogą współpracować z operacjami widoków zbiorczych w celu kierowania do wszystkich odpowiednich węzłów i działania na nich w oparciu o wartości pola. Ustawienie wartości nowego pola listy na podstawie wartości istniejącego pola listy dla grupy węzłów jest łatwe, gdy używasz Reguł.

Pamiętaj również, że jeśli Drupal sprawia ci problemy z operacją, zawsze opróżnij pamięć podręczną przed rozważeniem trudnej alternatywy.


0

Zakładam, że Twój klient chce, aby starsza treść zachowała pierwotną wartość, co oznacza, że ​​zmiana listy wyboru skutecznie zniszczy wszystkie poprzednie dane. Jeśli to nie dotyczy, to prawdopodobnie jedna z pozostałych odpowiedzi prawdopodobnie zadziała. Jeśli tak jest, nie można tak naprawdę zmienić listy wyboru bez utraty historii danych. Mógłbym pójść o wiele prostszą drogą, aby pozwolić na dane historyczne, jednocześnie czyniąc witrynę nieco bardziej przyszłościową - sugerowałbym użycie uprawnień terenowych:

* skonfiguruj nowe pole dla tej listy wyboru, używając taksonomii zamiast danych statycznych

* ustaw uprawnienie pola dla istniejącej listy wyboru jako WIDOK, ale nie EDYCJA przez nikogo oprócz administratora

Dzięki temu stare pole powinno pozostać widoczne i możliwe do przeszukiwania (dodaj nowy tytuł odzwierciedlający tylko jako starszą wersję), ale nie można go edytować. Zależy to oczywiście w dużej mierze od niestandardowych wyszukiwań, widoków itp., Które mogą wymagać dostosowania.

Sugeruję to (choć może to zabrzmieć zabójczo), ponieważ usunięcie tych danych, usunięcie historii, a na dłuższą metę może być katastrofalne. Możesz nawet użyć css, aby ukryć stare pole w węźle edycji, i zaczepu, aby ukryć je dla nowej zawartości (tam, gdzie nie ma ustawionej wartości). W ten sposób wyświetlałby się tylko w przypadku starszych treści.

Oczywiście możesz pójść o krok dalej dzięki niestandardowemu modułowi jednorazowemu, aby skopiować dane ze starej listy wyboru do nowej systematyki.


0

Prosty skrypt drush na ratunek! Aktualizujemy dane pól i tabele zmian pól i zastępujemy stare wartości nowymi przed ręczną zmianą ustawień pól.

Jeśli mamy coś takiego w naszych obecnych ustawieniach pola:

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

i chcesz zastąpić go następującym:

date=today|today
date=last2days|last2days

Najpierw uruchamiamy skrypt drush, a następnie zmieniamy ustawienia pól w interfejsie administratora.

Uwaga: Ten kod dotyczy pola z nazwą komputera 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

Użyłem drugiej sugestii Kenorba i działało to na aktualizację listy wartości w polu Drupal 7.52, Profile2 7.x-1.3. Więc jeśli otrzymałeś ostrzeżenie drupal: „Lista dozwolonych wartości: niektóre wartości są usuwane, gdy są w użyciu”. Następujące działania pozwoliły mi usunąć wartości z pola (profile2), bez usuwania lub zastępowania ich w bazie danych.

W katalogu głównym rdzenia Drupal znajduje się folder o nazwie moduły, a plik do edycji znajduje się w: moduły / pole / pole.moduł. TO JEST PLIK GŁÓWNY, musisz absolutnie przywrócić zmiany po zakończeniu aktualizacji wartości. Przełączyłem witrynę w tryb offline, tymczasowo zastąpiłem następujący blok kodu w (root 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();
}

DOKŁADNIE

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

Drupal przestał narzekać i mogłem zmienić listę. (W moim przypadku jest to wydział na liście wartości, które opuściły uniwersytet, ale nadal są powiązane z historią studentów, jako ich doradca, mentor itp.)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.