Удаление всех подписчиков из wp_users и wp_usermeta партиями по несколько тысяч
На моем сайте 70K подписчиков-спамеров, и они мне не нужны. Мне необходимо удалить всех подписчиков из wp_users и связанные метаданные из wp_usermeta с помощью запросов в adminer или phpmyadmin.
Но чтобы не перегружать сервер, как можно удалять по несколько тысяч записей за раз?
Вот базовый запрос, который мне нужен:
DELETE
FROM wp_users
INNER JOIN wp_usermeta ON wp_users.ID = wp_usermeta.user_id
WHERE meta_key = 'wp_capabilities'
AND meta_value LIKE '%subscriber%'
//но как выбрать по несколько тысяч записей за раз?
Но как выбрать по несколько тысяч записей за раз?

Мой любимый способ выполнить подобную задачу — не через взлом базы данных (что всегда может иметь побочные эффекты), а с помощью командной строки.
Например, при наличии рабочей установки WP CLI можно просто выполнить следующее:
wp user delete $(wp user list --role=subscriber --field=ID --number=10) --reassign=1
Параметр reassign
— это ID пользователя, которому будет перераспределён контент. Мы можем использовать "--number" (лимит), несмотря на то, что это плохо задокументировано, потому что WP_User_Query поддерживает этот параметр.
Вот и всё — чистая, однострочная команда для выполнения подобных операций.
Я рекомендую сначала проверить подзапрос "wp user list...", чтобы увидеть, каких пользователей он удалит. После выполнения команды вы увидите информацию вроде такой:
...
Success: Удалён пользователь 123 с https://example.com/.
Success: Удалён пользователь 124 с https://example.com/.
...

Вы можете использовать функцию WordPress для этого. wp_delete_user(); эта функция работает с ID пользователя. Вы можете получить ID всех подписчиков таким способом: get_users() возвращает отфильтрованных пользователей.
$get_subscribers = get_users('role=subscriber');
foreach($get_subscribers as $user){
wp_delete_user($user->ID);
}

У меня была похожая проблема, и после прочтения этого вопроса я создал этот плагин (адаптированный под ваш вопрос).
После установки он добавляет меню в админке в разделе Пользователи под названием Массовое удаление пользователей. При переходе на эту страницу плагин удаляет пользователей партиями по 20 человек, как указано в вашем SQL-запросе (мой оригинальный запрос немного отличался).
Вы можете сделать партии меньше или больше, но это позволяет удалить множество пользователей без таймаута сервера. Для большого количества спам-регистраций процесс может занять несколько минут.
Плагин использует jQuery для перезагрузки страницы после обработки каждой партии (это можно было бы сделать через AJAX, но мне нужно было быстрое решение).
Возможно, это кому-то пригодится. Скорее всего, вам нужно будет адаптировать SQL-запрос под вашу ситуацию.
<?php
/*
Plugin Name: Массовое удаление спам-пользователей
Description: Удаление спам-регистраций
Version: 0.1
Author: Steven
Text Domain: bulk-delete-spam-users
*/
add_action('admin_menu', 'my_users_menu');
function my_users_menu() {
add_users_page('Массовое удаление пользователей', 'Массовое удаление пользователей', 'read', 'bulk-user-delete', 'active_users_nodel');
}
function active_users_nodel() {
global $wpdb;
$result = array();
$result = $wpdb->get_results('
SELECT wp_users.id, wp_users.user_login FROM wp_users
INNER JOIN wp_usermeta ON wp_users.ID = wp_usermeta.user_id
WHERE meta_key = "wp_capabilities"
AND meta_value LIKE "%subscriber%"
');
$users = $result;
$i = 0;
echo '<div class="bud-box">';
$users_remain = $users ? 'true' : 'false';
$current_user = wp_get_current_user();
echo '<strong>Осиротевший контент будет перепривязан к:</strong><br />';
echo 'Имя пользователя: ' . $current_user->user_login . '<br />';
echo 'ID пользователя: ' . $current_user->ID . '<br />';
<h3>сейчас удаляется...</h3>
foreach($users as $user) {
$i++;
if($i < 20) {
wp_delete_user( $user->ID, $current_user->ID );
var_dump($user->user_login);
}
}
echo '</div>';
?>
<script>
(function($){
$(document).ready(function(){
var uremain = <?php echo $users_remain; ?>;
if( uremain == true){
location.reload();
}
});
})(jQuery);
</script>
<?php } ?>

Не получается активировать этот плагин. У вас ошибка в коде, нет echo вокруг <h3>currently deleting...</h3>

возможно с ограничением в случае больших объемов данных или ограниченных ресурсов:
DELETE
FROM wp_users
WHERE EXISTS
( SELECT t2.user_id
FROM wp_usermeta AS t2
WHERE t2.user_id = wp_users.ID
AND t2.meta_key ='wp_capabilities' AND meta_value LIKE '%customer%'
)
ORDER BY ID DESC
LIMIT 10000
