Как массово удалить всех пользователей без сообщений?

Вопрос или проблема

У меня есть 10 тысяч пользователей, около 98% из них никогда не публиковали пост (я имею в виду посты, а не комментарии).

Мне нужен способ массового удаления пользователей с 0 постами.

Метод должен учитывать все типы пользовательских постов и использовать правильную функцию WordPress для удаления пользователя так, как если бы его удаляли вручную через панель управления, а не просто удалять таблицу/строку в MySQL, так как это может привести к непредвиденным результатам.

Существует старый плагин, который это делает, но не учитывает все типы постов, поэтому его нельзя использовать.

Буду признателен за любую помощь.

Если у вас много пользователей для удаления, вы можете рассмотреть возможность использования команды wp user delete wp-cli, чтобы избежать таймаутов скрипта.

Вот пример SQL-запроса для удаления всех пользователей без постов любого типа и статуса.

Вы можете попробовать эту непроверенную однострочнку:

wp user delete $(wp db query "SELECT ID FROM wp_users WHERE ID NOT IN (SELECT DISTINCT post_author FROM wp_posts ) AND ID NOT IN (1,2,3)" | tail -n +2 ) --reassign=1

или в расширенной форме:

wp user delete $(wp db query
    "SELECT ID  
         FROM wp_users   
         WHERE ID NOT IN (  
            SELECT DISTINCT post_author FROM wp_posts 
         ) AND ID NOT IN (1,2,3)" | tail -n +2 
  ) --reassign=1

Обратите внимание, что мы добавили дополнительное ограничение AND ID NOT IN (1,2,3), чтобы убедиться, что эти пользователи не будут удалены (например, администраторы). Вам нужно будет настроить его под ваши нужды, а также префикс таблицы wp_.

Когда я кратко протестировал это для нескольких пользователей, я заметил, что мне пришлось добавить часть tail -n +2, чтобы избежать первых 3 строк в заголовке и границе таблицы вывода wp db query.

Здесь мы переназначаем все посты пользователю 1, чтобы избежать уведомления:

--reassign parameter not passed. All associated posts will be deleted. Proceed? [y/n] 

Надеюсь, вы сможете настроить его под свои нужды, например, смягчить условия удаления пользователя, добавив WHERE post_status="publish".

Примечание: Помните, что перед тестированием нужно сделать резервную копию!

Вот способ сделать это на PHP. Это может быть медленно и/или вызвать таймаут, но так как это однократное действие, это не должно слишком сильно влиять. Временно поместите код в functions.php или загрузите как новый плагин.

//* Вы не хотите запускать это на admin_init. Запустите один раз и деактивируйте
add_action( 'admin_init', 'wpse_262100_admin_init' );
function wpse_262100_admin_init() {
  $reserved_post_types = [
    'attachment',
    'revision',
    'nav_menu_item',
    'custom_css',
    'customize_changeset',
  ];

  //* Получить посты неподдерживаемых типов
  $post_types = array_diff( array_keys( get_post_types() ), $reserved_post_types );
  foreach( get_users() as $user ) {
    if( 0 == count_user_posts( $user->ID, $post_types ) ) {
      wp_delete_user( $user->ID );
    }
  }
}

Судя по исходному коду упомянутого вами старого плагина, посты, которые он не учитывает, это attachment и revision. Думаю, вы можете легко исправить это, удалив их из исходного кода файла плагина no-posts-user-delete.php

    AND NOT WP.post_type in ('attachment', 'revision')

Ответ от birgire требует вручную задать пользователей, которых вы не хотите удалять.

Изменив запрос немного, вы можете удалить только пользователей подписчиков (уровень 0)

SELECT ID FROM wp_users u WHERE ID NOT IN (SELECT DISTINCT post_author FROM wp_posts) AND 0 = (select m.meta_value from wp_usermeta m where m.meta_key='wp_user_level' and m.user_id = u.id);

wpcli однострочнка:

wp user delete $(wp db query "SELECT ID FROM wp_users u WHERE ID NOT IN (SELECT DISTINCT post_author FROM wp_posts) AND 0 = (select m.meta_value from wp_usermeta m where m.meta_key='wp_user_level' and m.user_id = u.id)" | tail -n +2 ) --reassign=1

Ответ или решение

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

Теория

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

WP-CLI — это мощный инструмент командной строки, позволяющий выполнять различные действия с установкой WordPress. Одной из его команд является wp user delete, которая позволяет удобно и безопасно удалять пользователей. Используя WP-CLI, можно избежать ограничений по истечению времени выполнения скрипта в PHP, что особенно важно при удалении большого количества пользователей.

Пример

Рассмотрим пример использования WP-CLI:

wp user delete $(wp db query "SELECT ID FROM wp_users WHERE ID NOT IN (SELECT DISTINCT post_author FROM wp_posts ) AND ID NOT IN (1,2,3)" | tail -n +2 ) --reassign=1

Эта команда делает следующее:

  1. Извлечение пользователи без постов: SQL-запрос выбирает пользователей из таблицы wp_users, чьи идентификаторы не встречаются в столбце post_author таблицы wp_posts, что означает, что данные пользователи не являются авторами ни одного поста.

  2. Исключение административных пользователей: Часть AND ID NOT IN (1,2,3) позволяет избежать удаления пользователей с определенными ID (например, администраторов). Эти ID необходимо настроить в зависимости от специфики вашего сайта.

  3. Удаление пользователей: Команда wp user delete удаляет выбранных пользователей, заметив, что флаг --reassign=1 передает все их посты указанному пользователю, чтобы избежать потерь данных.

  4. Фильтрация вывода: tail -n +2 используется для исключения заголовка SQL-запроса из списка.

Применение

Если WP-CLI недоступен или вы предпочитаете PHP-скрипт, рассмотрим следующий пример:

add_action( 'admin_init', 'bulk_delete_users_with_no_posts' );

function bulk_delete_users_with_no_posts() {
    $excluded_post_types = ['attachment', 'revision', 'nav_menu_item', 'custom_css', 'customize_changeset'];
    $post_types = array_diff(array_keys(get_post_types()), $excluded_post_types);

    foreach (get_users() as $user) {
        if (count_user_posts($user->ID, $post_types) === 0) {
            wp_delete_user($user->ID);
        }
    }
}

Объяснение:

  • Фильтрация типов записей: Мы исключаем незначимые для этой задачи типы постов, такие как attachment или revision, с помощью array_diff.

  • Удаление пользователей: Используя get_users(), перебираем всех пользователей и применяем count_user_posts для проверки наличия у них постов. Пользователи без постов удаляются.

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

Заключение

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

Оцените материал
Добавить комментарий

Капча загружается...