Как обработать хук удаления пользователя в InstantCMS 2

ЕСТЬ РЕШЕНИЕ ЗАКРЫТО
#1 28 мая 2015 в 19:18
Мой вопрос, наверное, больше адресован r2, но буду рад любой помощи или совету.

В компоненте необходимо обработать событие удаления пользователя из системы, следовательно использую хук user_delete.
Мне требуется почистить за пользователем данные которые ссылаются на созданные им записи в различных типах контента. Чтобы получить список записей хотел использовать функцию из модели контроллера "content" — getContentItems($ctype['name']);. Но проблема в том, что эта функция, в моем случае, вызывается уже после зачистки всех записей удаляемого пользователя в хуке user_delete, самим компонентом "content". Т.е. в БД нужных мне записей уже нет на момент поиска их в хуке моего компонента, т.к. он срабатывает позже хука компонента "content". Это связано с названием компонентов — очерёдность вызова всех хуков в InstantCMS 2 устанавливается в алфавитном порядке (см. ..\system\core\eventsmanager.php — getAllListeners() ) и т.к. название моего компонента следует за content'ом то обрабатывать уже нечего =(.

Решение проблемы вижу несколькими способами, но все они мне не нравятся:
1. хак — немного переписать функцию getAllListeners(), чтобы переместить в конец массива вызов хуков контроллера "content". Вроде бы самый логичный вариант, при том, что в iCMS 2 все крутится вокруг контента, и следовательно необходимо "пропустить вперед "чужие" контроллеры" в очереди хуков, мало-ли кому что понадобиться взять из записей, до момента их изменения/удаления. Но хак — это плохо.
2. хак — добавить в модель компонента "content" (deleteUserContent($user_id);) вызов хуков на удаление контента, как это сделано в теле экшена item_delete. Совсем плохая идея — из модели вызывать хуки. Или добавить в хук user_delete (компонента "content") вызов новых хуков, например 'content_user_delete':
  1. class onContentUserDelete extends cmsAction {
  2.  
  3. public function run($user){
  4.  
  5. cmsEventsManager::hook("content_user_delete", $user);
  6.  
  7. $this->model->deleteUserContent($user['id']);
  8.  
  9. return $user;
  10.  
  11. }
  12.  
  13. }
И снова хак, да к тому же еще вызов хука из хука((((
3. Обрабатывать все "ссылки" записей в БД моего компонента путем проверки на существование оригинала самой записи. Но тут встает вопрос производительности. Нужно перебрать все записи в БД компонента и сравнить их со всеми записями контента — очень не эффективное решение.

Через различные хаки (указанные в 1, 2 и другие) проблема легко решается, но возникают проблемы с поддержкой и продвижением компонента в последующих версиях InstantCMS 2. Поэтому, подытоживая выше-написанное, вопрос следующий: как узнать какие записи принадлежали удаляемому пользователю, если этих записей уже нет в БД, и затем удалить ссылки на эти записи в таблицах БД моего компонента?

P.S. Надеюсь получилось не слишком запутанно.
#2 28 мая 2015 в 19:41
Может зайти с другой стороны? При удалении контента записи удалить ссылки из вашего компонента.
#3 28 мая 2015 в 19:52
Loadырь, спасибо за отклик!
Удаление записи можно обработать через несколько хуков — "content_before_delete", "content_after_delete" и пару $ctype['name']-зависимых. У меня обрабатывается хук "content_after_delete", и если пользователь или админ/модератор удаляет запись, то все работает замечательно. Но в момент удаления пользователя из системы (через админ-панель), компонент "content" сам отрабатывает через свой внутренний хук, где чистит записи за удаляемым пользователем, при этом указанные выше хуки не вызываются, т.е. посторонние компоненты не знают, что content что-то удалил(((
Или же я вас не правильно понял?
#4 28 мая 2015 в 20:21
Да видимо без хака не обойтись. Ради спортивного интереса, пробовали ставить в файле \system\controllers\admin\actions\users_delete.php вместо этого
  1. $user = cmsEventsManager::hook('user_delete', $user);
это
  1. $user = cmsEventsManager::hookAll('user_delete', $user);
Интересно, ваш хук успеет получить данные о записях, пока хук контента их удаляет smile
#5 28 мая 2015 в 20:23
Loadырь, не пробовал, но ради спортивного интереса гляну))) Но нам с вами понятно, что это не выход smile
#6 28 мая 2015 в 20:30
Управление порядком вызова хуков будет реализовано когда хуки перенесутся в базу данных, вместо декларирования их в манифестах.
А сейчас выход, имхо, самый правильный тот, который уже написал Loadырь #2, но разумеется нужно поставить вам хук вручную на действие удаления записи при удалении из админки.

Ну если совсем без хаков и изменения файлов системы, то можно финт винтом сделать.
Добавить в ваш манифест хук компонента контент (или любого другого контроллера), который вызывается заведомо раньше удаления записей из базы, после этого обработать этот хук и в нем получить нужные вам данные до их удаления. сохранить их можно например в сессии, в свойстве ядра или вообще в глобальной переменной.
А после чего в своем уже штатном, так сказать, хуке забрать оттуда данные.
#7 29 мая 2015 в 12:23

Управление порядком вызова хуков будет реализовано когда хуки перенесутся в базу данных, вместо декларирования их в манифестах.

Fuze
А это стоит в планах? shockКак показывает практика есть случаи когда это очень бы помогало.

Ну если совсем без хаков и изменения файлов системы, то можно финт винтом сделать.
Добавить в ваш манифест хук компонента контент (или любого другого контроллера), который вызывается заведомо раньше удаления записей из базы, после этого обработать этот хук и в нем получить нужные вам данные до их удаления. сохранить их можно например в сессии, в свойстве ядра или вообще в глобальной переменной.
А после чего в своем уже штатном, так сказать, хуке забрать оттуда данные.

Fuze
Посмотрел какие хуки и в какой очередности вызываются (при удалении админом пользователя), получилось следующее:
1 — engine_start
2 — user_loaded
3 — user_delete
Думал зацепиться за user_loaded, но не тот это хук и не тот user)) Также без хаков подключиться к user_delete вышестоящих по алфавиту компонентов не получается((

Что-то я все больше склоняюсь к переименованию своего компонента, чтобы он начинался с "A" или "B".

А как разработчики смотрят на то чтобы перенести вызов хуков "content" в конец массива? Преимущества этого решения я описал в первом посте темы.
#8 31 мая 2015 в 18:56
Ждем нового релиза InstantCMS 2! smile
Используя этот сайт, вы соглашаетесь с тем, что мы используем файлы cookie.