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

8

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

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

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

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

Любая помощь приветствуется.

Майкл Роджерс
источник
3
Вы можете просто повторно использовать код в моем ответе здесь: wordpress.stackexchange.com/a/231485/24875
Кристина Купер

Ответы:

8

Если вы хотите удалить большое количество пользователей, вы можете использовать команду 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деталь, чтобы избежать трех верхних строк в заголовке и границы таблицы wp db queryвывода.

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

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

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

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

birgire
источник
Я не понимаю Повторных публикаций не должно быть, я не хочу удалять пользователей, которые разместили только тех, у кого 0 публикаций, повторных сообщений не должно быть.
Майкл Роджерс
1
Это не должно повлиять на этот конкретный пример, так как мы нацелены на любой тип сообщения и статус. Это было сделано только для того, чтобы избежать уведомления о пользовательской команде wp delete .. Вы также можете пропустить ее и нажать Yили использовать --yesдля всех. Если вы измените sql так, чтобы удалять только тех пользователей, которые опубликовали посты, то вам может понадобиться избежать, например, черновиков. Обратите внимание, что вы упомянули в вопросе пользователей, которые никогда не публиковали сообщения . Это строго означает, что они могут иметь черновики. Я предположил, что вы этого не имели в виду ;-) Пожалуйста, будьте очень конкретны в вопросе, что вы хотите удалить, чтобы избежать догадок. @MichaelRogers
birgire
4

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

//* You don't want to run this on admin_init. Run it once and deactivate
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',
  ];

  //* Get the non-reserved post types
  $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 );
    }
  }
}
Натан Джонсон
источник
1

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

    AND NOT WP.post_type in ('attachment', 'revision')
Николай
источник
Сожалею! Я имел в виду нестандартные типы постов. Автор написал на форумах поддержки, что пользовательские типы сообщений не считаются только «сообщениями», поэтому он будет удалять пользователей, создавших пользовательские сообщения, и это не хорошо.
Майкл Роджерс
@MichaelRogers Не думаю, что он это имеет в виду. Как я уже сказал, единственными типами, которые не учитываются, являются два, которые я написал. Поэтому плагин должен влиять на пользовательские типы сообщений. Они хранятся в одной таблице базы данных. Я предлагаю вам сделать резервную копию, а затем попробовать плагин и посмотреть, работает ли он так, как вы хотите. Если это не так, восстановите резервную копию.
Николай