Come posso rimuovere elementi dall'elenco dei valori consentiti di un campo di selezione che contiene dati per i valori?


16

Ho creato un tipo di contenuto che ha un campo elenco / seleziona un'opzione e ho inserito le coppie chiave | valore in base alle necessità affinché l'elenco di selezione funzioni.

I dati sono stati inseriti ed è stato deciso che alcuni termini non si applicano più e che devono essere eliminati.

Tuttavia, quando provo a rimuovere tali termini, ottengo il seguente errore:

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

Ovviamente, nella vita di un progetto, i valori cambieranno. Qual è un modo pratico per rimuovere elementi una volta che i nodi sono associati ai termini elencati?

Questa è la cosa più vicina che ho potuto trovare:

https://drupal.org/node/1653012

Fa riferimento a un plugin d6 e ad alcuni trucchi con le patch a cui preferirei non ricorrere. Se alla fine ho dovuto ricorrere all'uso della patch per rimuovere il controllo di validazione su quel campo, c'è qualche danno nel lasciare quegli elementi orfani sui nodi a cui erano associati?

Aggiornamento, mi sono imbattuto di nuovo in questo problema con un cliente governativo che, negli ultimi 7 anni di un sito Drupal, ha avuto 50 stati e territori in un elenco selezionato. Ora, la politica è cambiata e non è più necessario includere i territori. Essere in grado di rimuovere elementi dagli elenchi selezionati è importante, e quindi offro una taglia.

Sto cercando una soluzione sicura per poter rimuovere elementi da un elenco selezionato. Quello che non so è se quella soluzione dovrebbe aggiornare uno dei nodi poiché non sono sicuro di come siano archiviati i valori dei campi in relazione al contenuto totale di un nodo.

Sono contento di una soluzione SQL pura da eseguire in MySQL; o sto cercando un modulo.


3
Ovviamente, nella vita di un progetto, i valori cambieranno. Discuterei che - i valori per un elenco di selezione statica dovrebbero essere definiti all'inizio del progetto. Se è necessario che sia flessibile, è necessario utilizzare un termine di riferimento anziché un elenco statico. Le liste statiche sono per cose come il sesso (maschio / femmina) che, a meno che non abbiamo un cambiamento serio nelle cose, non è probabile che cambi presto. E se lo fa, verrà aggiunto , non rimosso . Ogni volta che ho commesso questo "errore" ho sempre trovato il modo migliore per tornare indietro è quello di eseguire query manuali sui dati
Clive

1
Vuoi rendere dinamico questo elenco? essere dinamico nella creazione e nella cancellazione.
M ama D,

1
Sì, suppongo che sia solo un'opinione: la casa automobilistica sarebbe sempre un tipo di nodo o un vocabolario per qualsiasi sito che costruirò. Poiché il produttore è una categoria di auto (o categoria di auto che qualcuno ripara), ha più senso come tassonomia per me piuttosto che un tipo di contenuto. Ma so che non aiuta ... Sarei cauto nel lasciare i dati orfani nel DB, è molto difficile dire quale effetto potrebbe avere senza sapere esattamente cosa è installato sul tuo sito e come è configurato
Clive

1
Cosa c'è che non va in views_bulk_operations?
donquixote,

1
eh, nessuna di queste risposte ha ancora voti: /
tenken

Risposte:


7

Di recente ho fatto qualcosa del genere con il seguente approccio.

  1. Aggiungi i nuovi valori consentiti.
  2. Aggiungi un'impostazione per configurare i valori "attivi".
  3. Filtrare i valori "inattivi" dalla visualizzazione nel modulo.

per esempio:

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

}

In questo modo i dati legacy vengono conservati per riferimento, il modulo viene convalidato e l'integrità dei dati è intatta.


1
Questa opzione è essenzialmente non distruttiva (ovvero, nascondere elementi anziché eliminare), ed è probabilmente il miglior punto di partenza fino a quando non si è in grado di determinare il miglior modo di agire su come gestire qualsiasi entità che abbia opzioni obsolete.
mpdonadio

3

Come so, tutti i dati dei campi sono memorizzati in 2 tabelle: field_data_field_FIELDNAME e field_revision_field_FIELDNAME. E ho trovato la conferma del mio pensiero qui: /programming//a/7773117/1300562

Quindi per rimuovere i valori di campo non necessari è necessario eliminare questi valori dalle tabelle sopra menzionate e quindi rimuoverli dall'elenco dei valori consentiti.

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

Passaggio 2.
Rimuovere le coppie non necessarie di chiave | valore dalla pagina delle impostazioni del campo e inviare il modulo per salvare le modifiche.
Successivamente, la cache deve essere cancellata automaticamente, ma se è ancora possibile vedere i valori dei campi rimossi nelle pagine dei nodi, cancellare manualmente la cache.

PS Di recente ho riscontrato un problema simile e ora preferisco utilizzare i campi di tipo "Riferimento termine" o (ancora meglio) "Riferimento entità" anziché un elenco di valori di testo. Quando si utilizza il campo di riferimento, è possibile creare un vocabolario separato per ciascun campo e creare / modificare / eliminare i termini in qualsiasi momento.


Se il campo si ripete, quelle query non modificheranno i delta per i dati rimanenti.
mpdonadio

1

Prima di tutto controlla se hai dei valori consentiti specificati nel campo? In tal caso, un'altra opzione non verrà convalidata. Quindi prova a rimuovere prima i valori dalla scheda Impostazioni campo.

In alternativa hai 2 opzioni:


1.

Rimuovi tutti i valori che hai inserito nell'elenco dei valori consentiti che sono in uso dagli account utente. Ad esempio, è possibile eseguire una query SQL per trovare questi:

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

o creare una vista utente che mostri quali account utente hanno il valore che si desidera rimuovere dall'elenco dei valori consentiti.


2.

Se non si desidera rimuovere valori dai campi, questo può essere ottenuto tramite l'hacking.

Attenzione, questa non è una soluzione suggerita per la produzione e dovresti sapere cosa stai facendo!

  1. Trova e modifica i moduli / field / field.module
  2. Trova la funzione field_has_data () e aggiungi return TRUE;nella prima riga della funzione.

    function field_has_data($field) {
      return FALSE; // HACK !!!
      $query = new EntityFieldQuery();
  3. Salvare nuovamente il campo con i valori desiderati.
  4. Rimuovi l'hack non appena lo fai.

0

Penso che tu possa effettivamente farlo usando il modulo Operations Bulk Operations .

  1. aggiungi una nuova opzione nel campo che desideri sostituire. ad esempio: na | NA
  2. creare un nodo Visualizza per elencare contenere con quel campo
  3. aggiungi i campi "Operazioni collettive: contenuto" in quella vista
  4. seleziona "Modifica valori entità" e "mostra token disponibili" (seleziona Tutto sui valori visualizzati)
  5. Aggiungi il campo che desideri modificare in Criteri filtro ed "esponi" i filtri
  6. imposta il percorso dell'URL su quella vista
  7. Vai a quella pagina di visualizzazione e modifica
  8. Ora, usa le funzionalità di esporre e operazioni per modificare l'opzione del campo
  9. Fatto

0

Ecco un miglioramento per la risposta HL che penso sia la migliore:

Per riassumere, è necessario assegnare nuovi valori al contenuto a cui sono assegnati "vecchi" valori per il campo selezionato.

Oltre alle operazioni collettive di Views , sarà necessario installare e abilitare il modulo Viste di amministrazione . Con questo modulo, hai già una vista immediata con operazioni in blocco abilitate (vedi solo admin / contenuto una volta abilitato). Poi:

1) Vai su admin / struttura / visualizza una vista di modifica "Amministrazione: Nodo"

2) Aggiungi una nuova visualizzazione della pagina per la vista usando il pulsante "Aggiungi -> Pagina" in alto

3) Assegnare un percorso al nuovo display: Esempio admin / content / custom

4) Aggiungi un nuovo filtro per il campo selezionato: Seleziona operatore "è uno di" e quindi seleziona tutte le opzioni che desideri eliminare

5) Salva la vista

6) Vai su admin / content / custom Ora vedi tutti i contenuti che devi modificare in blocco (cambia valore per il tuo campo selezionato)

7) Seleziona tutte le righe facendo clic sulla prima casella di controllo a sinistra della tabella (se è presente più di una pagina, seleziona anche un pulsante che dirà "Seleziona tutte le X righe in questa vista")

8) Selezionare l'operazione "cambia valore" e premere "Esegui"

9) Per il campo selezionato, selezionare un nuovo valore per sovrascrivere quelli che si desidera eliminare

10) Selezionare la casella di controllo per quel campo di selezione

11) Fare clic su Avanti e il gioco è fatto


0

Sembra che il tuo problema con Drupal sia basato su un problema di dati più profondo: cosa succede alle entità che attualmente utilizzano i valori dell'elenco deprezzati? Questa domanda è alla radice del messaggio di errore che Drupal ti sta inviando.

Diamo un'occhiata più da vicino al tuo esempio di stato / territorio. Il tuo cliente utilizza da anni un sistema che tratta stati e territori allo stesso modo e ha creato un enorme gruppo di nodi che contengono sia stati che territori. Quindi un giorno, i poteri che decidono che i territori devono essere gestiti in modo diverso e che il menu a discesa per l'assegnazione della regione non dovrebbe più contenere territori. Grande. Basta creare una vista che utilizza i filtri standard per eseguire il rendering di un elenco di tutti i nodi del territorio e utilizzare Viste Operazioni collettive per modificare tutti i valori della loro regione in ... quale ... forse un 51 ° stato chiamato altro? Il destino dei territori è una domanda molto seria. La soluzione deve includere un metodo per preservare o spostare lo stato del territorio. Potrebbe essere necessario creare un nuovo campo elenco chiamato "Territorio"

Per eseguire queste modifiche dovrai utilizzare le Regole con Visualizza operazioni in blocco. Se non sai molto delle regole, ti preghiamo di dedicare un po 'di tempo a sapere come funzionano. Le regole ti danno la possibilità di manipolare le informazioni in base a trigger, condizioni e azioni. Dopo aver appreso le regole, potresti scoprire che le risposte che stai cercando si presenteranno intuitivamente. Fondamentalmente, dovrai creare una regola, che viene attivata da un'operazione in blocco, che prenderà di mira tutti i territori e rimuoverà, riassegnando, rinominando o separandoli in altro modo dal corpo principale di informazioni. La regola deve essere in grado di memorizzare lo stato del territorio in qualche modo, mentre allo stesso tempo, impostare il menu a discesa dello stato su "altro" o "N / A". Questo potrebbe essere tutto ciò che è necessario. Altrimenti...

Al termine della riassegnazione, dovrebbe essere una semplice operazione modificare il campo elenco originale e rimuovere i nomi dei territori. Tuttavia, se il sistema non consente ancora di modificare l'elenco, potrebbe essere necessario creare un nuovo campo elenco, quindi utilizzare Operazioni collettive e regole viste per rivedere tutti i valori di stato correnti e riassegnarli al nuovo elenco. Le regole possono funzionare con Views Bulk Operations per indirizzare tutti i nodi rilevanti e agire su di essi in base ai valori dei campi. L'impostazione del valore di un nuovo campo elenco in base al valore di un campo elenco esistente per un gruppo di nodi è facile quando si utilizzano le Regole.

Ricorda inoltre, se Drupal ti dà problemi con un'operazione, scarica sempre la cache prima di considerare un'alternativa difficile.


0

Suppongo che il tuo cliente desideri che il contenuto legacy rimanga al suo valore originale, il che significa che cambiare l'elenco selezionato distruggerà efficacemente tutti i dati precedenti. Se questo non è un problema, probabilmente una qualsiasi delle altre risposte funzionerebbe. In tal caso, non è possibile modificare l'elenco di selezione senza perdere la cronologia dei dati. Potrei seguire un percorso molto più semplice, per consentire i dati storici, rendendo il sito un po 'più a prova di futuro - Suggerirei di utilizzare le autorizzazioni di campo:

* imposta un nuovo campo per quell'elenco di selezione utilizzando una tassonomia anziché i dati statici

* imposta l'autorizzazione di campo per l'elenco di selezione esistente come VISUALIZZA, ma non MODIFICA da parte di nessuno tranne amministratore

Con questo, il vecchio campo dovrebbe rimanere visualizzabile e ricercabile (aggiungi un nuovo titolo che lo rifletta solo come legacy) ma non modificabile. Questo ovviamente dipende fortemente dalle ricerche personalizzate, dalle visualizzazioni, ecc. Che potrebbero dover essere modificate.

Suggerisco questo (per quanto disordinato possa sembrare) perché rimuovere quei dati, rimuove la cronologia e ciò potrebbe finire per essere devastante a lungo termine. Puoi anche usare CSS per nascondere il vecchio campo nel nodo di modifica e un hook per nasconderlo per il nuovo contenuto (dove non ha un valore impostato). In questo modo, verrebbe mostrato solo per quel contenuto legacy.

Ovviamente, potresti fare un ulteriore passo avanti con un modulo personalizzato una tantum per copiare i dati dal vecchio elenco di selezione alla nuova tassonomia.


0

Una semplice sceneggiatura in soccorso! Aggiorniamo i dati dei campi e le tabelle di revisione dei campi e sostituiamo i vecchi valori con quelli nuovi prima di modificare manualmente le impostazioni del campo.

Se abbiamo qualcosa di simile nelle nostre attuali impostazioni sul campo:

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

e vuoi sostituirlo con il seguente:

date=today|today
date=last2days|last2days

Prima eseguiamo lo script drush e poi cambiamo le impostazioni del campo nell'interfaccia utente dell'amministratore.

Nota: questo codice è per un campo con nome macchina 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

Ho usato il secondo suggerimento di Kenen e ha funzionato per aggiornare l'elenco dei valori in un campo Drupal 7.52, Profile2 7.x-1.3. Quindi se stavi ricevendo l'avvertimento drupal: "Elenco dei valori consentiti: alcuni valori vengono rimossi mentre attualmente in uso". Quanto segue mi ha permesso di rimuovere i valori dal campo (profilo2), senza rimuoverli o sostituirli nel database.

Nella directory principale di Drupal core, c'è una cartella chiamata module, e il file da modificare si trova in: modules / field / field.module. QUESTO È UN FILE FONDAMENTALE, è necessario ripristinare assolutamente le modifiche al termine dell'aggiornamento dei valori. Ho portato il sito offline, sostituito temporaneamente il seguente blocco di codice in (drupal root) /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();
}

CON ESATTAMENTE

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

E drupal ha smesso di lamentarsi e sono stato in grado di modificare l'elenco. (Nel mio caso, è facoltà nella lista di valori che hanno lasciato l'università, ma sono ancora associati a un record di studenti, come loro consigliere, mentore, ecc.)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.