Drupal: удаляем/переносим посты и прочее имущество одного пользователя к другому

Изображение пользователя andyceo.

Друзья, рано или поздно наверняка каждый из вас, возясь с сайтами на Drupal, сталкивался с задачей, когда надо было все посты, комментарии, картинки и прочие вещи, нажитые одним пользователем, передать другому пользователю, а старого пользователя удалить. Столкнулся с этим и я, ваш покорный слуга. Предлагаю Вашему вниманию краткую шпаргалку действий, которая поможет Вам быстро и без потерь перенести имущество от одного юзера к другому.

Внимание! Предупреждение! Если Вы приняли решение использовать любой нижеследующий код, то вся ответственность за его результаты и последствия будет лежать на Вас и только на Вас! Автор предлагает всё нижеследующее только как свой собственный опыт и не гарантирует корректной работы кода в Вашем конкретном случае. НЕ ЗАБУДЬТЕ СДЕЛАТЬ РЕЗЕРВНУЮ КОПИЮ ВАШЕЙ БАЗЫ ДАННЫХ ПЕРЕД ИСПОЛЬЗОВАНИЕМ ЛЮБОГО НИЖЕСЛЕДУЮЩЕГО КОДА!

Будем делать это мы посредством выполнения SQL-запросов - так будет быстрее всего. Поэтому сначала мы подготовим соответствующие запросы к базе данных. Имейте в виду, что имена таблиц в запросах я указал в фигурных скобках (как это принято в среде разработчиков Drupal), вам же нужно будет заменить имя таблицы в фигурных скобках на реальное имя таблицы с Вашим префиксом или постфиксом, если запрос вы будете выполнять непосредственно на сервере (через phpMyAdmin, например).

/* меняем автора документов (нод) */
UPDATE {node} SET uid='#OLD_UID#' WHERE uid='#NEW_UID#';
UPDATE {node_revisions} SET uid='#OLD_UID#' WHERE uid='#NEW_UID#';
 
/* меняем автора комментариев */
UPDATE {comments} SET uid='#OLD_UID#' WHERE uid='#NEW_UID#';
 
/* если используется модуль IMCE_Gallery, меняем автора (владельца) галлерей: */
UPDATE {imce_gallery} SET uid='#OLD_UID#' WHERE uid='#NEW_UID#';
UPDATE {imce_gallery_items} SET uid='#OLD_UID#' WHERE uid='#NEW_UID#';
 
/* обновляем историю просмотров документов */
UPDATE {history} SET uid='#OLD_UID#' WHERE uid='#NEW_UID#';
 
/* если используется модуль LiveJournal CrossPoster, делаем привязку LiveJournal-дневника к новому пользователю: */
/* Внимание! Если дневник наверняка не принадлежит новому пользователю, НЕ ДЕЛАЙТЕ ЭТОГО! */
/* Иначе вы можете дать доступ стороннему человеку к чужому дневнику! */
UPDATE {ljxp} SET uid='#OLD_UID#' WHERE uid='#NEW_UID#';
 
/* присваиваем роли старого пользователя новому: */
UPDATE {users_roles} SET uid='#OLD_UID#' WHERE uid='#NEW_UID#';

После того, как вы выполнили эти запросы (естественно, вам нужно заменить '#OLD_UID#' на uid Вашего старого пользователя, а '#NEW_UID#' - на uid нового), Вам необходимо подкорректировать синонимы, связанные со старым пользователем, на новые. Этот шаг я делал вручную, мне понадобилось изменить синоним на самого юзера, на его блог и на его галлерею (IMCE_Gallery).

Те, кто использует модуль IMCE_Gallery, используют и модуль IMCE. А IMCE, как известно, позволяет пользователям иметь своё собственное хранилище файлов на Вашем сайте, и предоставляет удобный доступ к нему. Когда пользователь загружает какой-либо файл, он сохраняется в его собственной папке. По умолчанию IMCE создаёт папки вида u5, u1, u134, где буква u означает user, а число непосредственно сразу за буквой - это uid юзера. Таким образом, если наш старый пользователь создал документ и в него вставил картинку или файл, то путь до этой, например, картинки, будет примерно таким: files/u5/my_picture.gif. Разумеется, этот файл будет отсутствовать в директории файлов нового пользователя (т.к. файл пока никто не копировал из старой директории в новую). Если же файлы из пользовательской директории старого пользователя, переместить в пользовательскую директорию нового пользователя, то все файлы и картинки, закачанные старым пользователем, перестанут загружаться (т.к. путь до них прописан с использованием старой директории: files/u5/my_picture.gif). Для того, чтобы всё было корректно, нам необходимо поправить пути до файлов во всех документах старого юзера.

Найти и посмотреть ноды, в которых используются старые пути для файлов, можно с помощью запроса:

/* смотрим документы, которые используют старые пути в своём контенте */
SELECT `body`, `teaser` FROM {node_revisions} WHERE `body` LIKE '%/#OLD_DIRECTORY#/%' OR `teaser` LIKE '%/#OLD_DIRECTORY#/%';

Заметьте, что вместо #OLD_DIRECTORY# вы должны вставить пользовательскую папку Вашего старого юзера. Так, например, если у вас старый пользователь имеет uid=5, IMCE настроен сохранять файлы в директории вида uномер_пользователя, то старая папка будет u5. Обратите внимание, что в запросе папка обрамлена слешами: /u5/, это нужно для того, чтобы найти именно пути, а не какую-то другую часть поста.

Для этого составим и выполним следующие SQL-команды, с использованием замечательной функции MySQL REPLACE():

/* меняем пути до файлов в новой директории. (предварительно скопировав их из старой директории в новую) */
UPDATE {node_revisions} SET `body` = REPLACE(`body`,'/#OLD_DIRECTORY#/','/#NEW_DIRECTORY#/'), `teaser` = REPLACE(`teaser`,'/#OLD_DIRECTORY#/','/#NEW_DIRECTORY#/') WHERE `body` LIKE '%/#OLD_DIRECTORY#/%' OR `teaser` LIKE '%/#OLD_DIRECTORY#/%';

Не забудьте поменять #OLD_DIRECTORY# на имя пользовательской папки Вашего старого юзера, а #NEW_DIRECTORY# - на имя пользовательской папки Вашего нового юзера.

Возможно, после всех этих операций Вам понадобиться сбросить кеш Drupal, чтобы ноды закешировались заново:

TRUNCATE TABLE {cache};

Мне же этот шаг не понадобился, всё было хорошо.

Код для регенерации анонсов (teasers) у всех документов (nodes) Вашего сайта

Когда я делал последний шаг, я немного ошибся и выполнил несколько неправильный запрос, в результате которого у меня все анонсы стали равны основному содержанию - вместо тизеров отображались полные версии статей. (В статье-то я, конечно, указал уже корректный запрос).

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

<?php
echo 'Fixing the latest node revision teasers for these published items:<br />';
$result = db_query(db_rewrite_sql("SELECT n.nid, n.status, n.vid, r.body, r.format FROM {node} n LEFT JOIN {node_revisions} r ON n.vid = r.vid WHERE n.status = '1' ORDER BY n.nid DESC"));
while (
$node = db_fetch_array($result)) {
    
$teaser = node_teaser($node['body'], $node['format']);
    
db_query(db_rewrite_sql("UPDATE {node_revisions} n SET n.teaser ='%s' WHERE n.vid='%d'"), $teaser, $node['vid']);
    echo
$node['nid']." / ".$node['vid']."<br/>";
    }
?>

Код взят отсюда: Fix Node Teasers

Он был написан для Drupal 4.7, но подходит и для Drupal 5.8. Я совсем немного подкорректировал его - поставил <br /> в первой строке.

Самый простой и быстрый способ выполнить его - это под суперадмином создать страницу (ноду) на вашем сайте, разместить в теле страницы этот код (включая теги <?php ?>) и сохранить её. Обязательно уберите галочку "Опубликовать"! Тем самым вы сделаете невидимой эту страницу для всех, кроме автора, т.е. в нашем случае, на эту страницу никто не будет иметь доступа, кроме админа.

На этом вроде бы всё. Не забывайте делать резервную копию Ваших данных перед любыми экспериментами! Делать её после уже может быть поздно! Пишите в комментариях Ваши вопросы и замечания, отвечу всем по мере сил. Спасибо за внимание и удачи, друпаловоды! :)

Добавьте страницу в закладки. Перейти к верху страницы
Синдикация материалов