Можно ли подключиться к событию набора переменных()?


Я хотел бы отслеживать событие системных изменений, чтобы сделать их обратимыми. При проверке variable_set() я вижу, что для этого события не предусмотрен крюк. Есть ли у меня какой-нибудь способ сделать это?

Я могу изменить, чтобы подключиться к формам настроек, но нужно отслеживать множество форм настроек, если я смогу напрямую подключиться к variable_set(), код станет намного проще.

Я также могу отслеживать изменения переменных с помощью модулей features + strongarm, но лучше, если администратор Drupal можно просматривать историю переменных, не касаясь кода.

 8
Author: Andy Truong, 2013-09-30

3 answers

Похоже, что использовать только Drupal невозможно, что означает:

variable_set() сам по себе не вызывает никаких зацепок, но использует db_merge(). Эта функция использует MergeQuery класс. Теперь было бы неплохо зацепиться за hook_query_alter(), но это работает только для классов запросов, которые реализуют QueryAlterableInterface интерфейс. К сожалению, этот интерфейс теперь реализован только SelectQuery и тот SelectQueryExtender занятия, а не по MergeQuery класс.

Обратите внимание, что даже если вы найдете способ создать дочерний класс MergeQuery, это позволит реализовать QueryAlterableInterface, и заставьте Drupal использовать его. hook_query_alter() работает только с запросами, имеющими теги, и variable_set() не помечает свой запрос, поэтому крючок все равно не будет использоваться, если вы не хотите взломать ядро. Но если да, то вам все это не нужно, вы можете просто взломать вызов по телефону.

Если вы чувствуете себя хардкорным, вы можете использовать более косвенный Подход PHP: $conf - это глобальный массив переменных конфигурации; вы можете написать модуль, который заменит его объектом , действующим как массив, как описано в разделе Переполнение стека. Чтобы сделать его хорошей заменой, вам необходимо реализовать ArrayAccess. Перенесите все значения из исходного $conf в свой объект. Затем, в ArrayAccess::offsetSet() реализуйте свою логику ведения журнала.

 11
Author: Mołot, 2018-01-07 21:09:44

Вы могли бы использовать триггер базы данных, который был бы быстрее кода.

Вот документ MySQL.

  1. Создайте таблицу для хранения старых значений

    CREATE TABLE variable_backup
    (
        name varchar(128) not null,
        value longblob,
        updated datetime not null,
        primary key (name, updated)
    );
    
  2. Создайте свои триггеры, один для вставки и один для обновления:

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

Теперь все ваши обновления и вставки будут записывать старые значения в variable_backup.

 6
Author: Scott Joudry, 2013-09-30 14:39:43

Как вы можете видеть в исходном коде, variable_set() не запрашивает крючки или изменения, например, нет module_invoke_all() или drupal_alter() звонит туда.

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

Тем не менее, вы можете прослушать запрос db_merge() с помощью специально размещенного hook_query_alter() и выполните там некоторую дополнительную обработку, но, как указал Молот, hook_query_alter() вряд ли сможет настроить таргетинг на запрос db_merge().

В качестве альтернативы, вы могли бы, возможно, сделать снимок таблицы переменных, чтобы сравните его с предыдущими версиями этой таблицы или реализуйте какую-либо другую форму хранения переменных версий для сравнения.

 5
Author: David Thomas, 2018-01-07 21:12:27