È possibile agganciare all'evento variabile_set ()?


8

Vorrei tracciare l'evento dei cambiamenti di sistema, per renderli riverificabili. Durante il controllo di variabile_set (), vedo che non è stato fornito alcun hook per quell'evento. C'è un modo per me di farlo?

Posso modificare per agganciare i moduli delle impostazioni, ma ci sono molti moduli di impostazioni da tracciare, se posso agganciare direttamente a variabile_set (), il codice diventa molto più semplice.

Posso anche tenere traccia delle modifiche alle variabili con funzionalità + moduli strongarm, ma è meglio se l'amministratore Drupal può sfogliare la cronologia delle variabili senza toccare il codice.

Risposte:


11

Sembra che sia impossibile usare solo Drupal, il che significa:

variable_set()di per sé non invoca alcun gancio, ma utilizza db_merge(). Quella funzione sta usando la MergeQueryclasse. Ora, sarebbe bello agganciarlo hook_query_alter(), ma funziona solo per le classi di query che implementano l' QueryAlterableInterfaceinterfaccia. Purtroppo, questa interfaccia è da adesso implementata solo dai SelectQuerye le SelectQueryExtenderclassi, non dalla MergeQueryclasse.

Nota che anche se troverai un modo per creare una classe figlio di MergeQuery, ciò implementerà QueryAlterableInterfacee farà in modo che Drupal lo usi. hook_query_alter()Funziona solo su query che hanno tag e variable_set()non tag la sua query, quindi l'hook non verrebbe usato comunque, a meno che tu non sia disposto a hackerare core. Ma se lo sei, non hai bisogno di tutto ciò, potresti semplicemente hackerare in una chiamata hook.

Se ti senti hardcore puoi usare un approccio PHP più indiretto: $confè un array globale di variabili di configurazione; puoi scrivere un modulo che lo sostituirà con un oggetto che agisce come un array, come descritto in Stack Overflow . Per renderlo un buon sostituto devi implementarlo ArrayAccess. Estrai tutti i valori dall'originale $confal tuo oggetto. Quindi, ArrayAccess::offsetSet()implementare la logica di registrazione.


Ho dimenticato questa mia vecchia risposta e ho già scoperto come fare praticamente qualsiasi cosa con $confallora: D Spero che la mia risposta aggiornata possa aiutare qualcuno.
Mołot,

Sono impressionato! : D
Letharion,

@Letharion Grazie :) Una volta mi piaceva la "magia che agisce come ..." in PHP, e me ne ricordo ancora un po ';)
Mołot

6

È possibile utilizzare un trigger di database, che sarebbe più veloce del codice.

Ecco il documento MySQL .

  1. creare una tabella per memorizzare vecchi valori

    CREATE TABLE variable_backup
    (
        name varchar(128) not null,
        value longblob,
        updated datetime not null,
        primary key (name, updated)
    );
  2. crea i tuoi trigger, uno per l'inserimento e uno per l'aggiornamento:

    CREATE TRIGGER backup_variable_update BEFORE UPDATE ON variable
        FOR EACH ROW
            INSERT INTO variable_backup (name, value, type, updated) VALUES (OLD.name, OLD.value, "update", NOW());
    
    CREATE TRIGGER backup_variable_insert BEFORE INSERT ON variable
        FOR EACH ROW
            INSERT INTO variable_backup (name, value, type, updated) VALUES (NEW.name, NEW.value, "insert", NOW());

Ora tutti i tuoi aggiornamenti e inserimenti registreranno i vecchi valori in variabile_backup.


Mi piace, pulito e semplice. Probabilmente anche più veloce del mio metodo. Più limitato, ma abbastanza per fare ciò di cui ha bisogno OP, se ha accesso MySQL sufficiente.
Mołot,

Mi piace così Ma penso che dobbiamo tenere traccia anche delle informazioni dell'agente utente
Andy Truong,

Dubito che le informazioni sarebbero disponibili per il database.
Scott Joudry,

@AndyTruong che le informazioni non saranno nel database, mi dispiace. Ho provato a guardarmi intorno ma è impossibile indovinarlo con i dati nella tabella delle sessioni e solo alcune query selezionate sono modificabili, quindi non c'è modo di aggiungerle. Quindi il mio metodo "hardcore" è lì per te. Spero che tu abbia avuto successo nel realizzarlo, in caso contrario - fai una nuova domanda collegandolo ad esso e commenta che l'hai fatto.
Mołot,

5

Come puoi vedere nel codice sorgente, variable_set()non richiede richieste di hook o alterazioni, ad esempio no module_invoke_all()o drupal_alter()chiamate lì.

function variable_set($name, $value) {
  global $conf;

  db_merge('variable')->key(array('name' => $name))->fields(array('value' => serialize($value)))->execute();

  cache_clear_all('variables', 'cache_bootstrap');

  $conf[$name] = $value;
}

Tuttavia, potresti essere in grado di ascoltare la db_merge()query con un posizionamento speciale hook_query_alter()e di eseguire qualche elaborazione aggiuntiva lì, ma, come sottolineato da Molot, hook_query_alter()sembra improbabile che sia in grado di indirizzare la db_merge()query.

In alternativa, potresti forse cron snapshot della tabella delle variabili per diffonderla rispetto alle revisioni precedenti di quella tabella, oppure implementare qualche altra forma di archiviazione delle revisioni variabili per confrontare.


1
Se hook_query_alter può essere utilizzato su questa query, mi piacerebbe vedere come. In 8 QueryAlterableInterfaceè effettivamente implementato da Querysolo. Ma in 8 la gestione della configurazione viene comunque ricostruita. E in 7 solo le query selezionate contrassegnate sono modificabili per quanto posso vedere. Ma forse mi sto perdendo qualcosa?
Mołot,

1
No, hai ragione, hook_query_alter era un'ipotesi, ma non fattibile in D7 in questo caso, grazie.
David Thomas,

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.