updated plugin ActivityPub version 8.3.0
This commit is contained in:
@ -0,0 +1,302 @@
|
||||
<?php
|
||||
/**
|
||||
* Self-Destruct CLI Command.
|
||||
*
|
||||
* @package Activitypub
|
||||
*/
|
||||
|
||||
namespace Activitypub\Cli;
|
||||
|
||||
use Activitypub\Activity\Activity;
|
||||
use Activitypub\Collection\Actors;
|
||||
use Activitypub\Collection\Outbox;
|
||||
use Activitypub\Collection\Remote_Posts;
|
||||
|
||||
use function Activitypub\add_to_outbox;
|
||||
|
||||
/**
|
||||
* Remove the blog from the Fediverse.
|
||||
*
|
||||
* @package Activitypub
|
||||
*/
|
||||
class Self_Destruct_Command extends \WP_CLI_Command {
|
||||
|
||||
/**
|
||||
* Remove the entire blog from the Fediverse.
|
||||
*
|
||||
* This command permanently removes your blog from ActivityPub networks by sending
|
||||
* Delete activities to all followers. This action is IRREVERSIBLE.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* [--status]
|
||||
* : Check the status of the self-destruct process instead of running it.
|
||||
* Use this to monitor progress after initiating the deletion process.
|
||||
*
|
||||
* [--yes]
|
||||
* : Skip the confirmation prompt and proceed with deletion immediately.
|
||||
* Use with extreme caution as this bypasses all safety checks.
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* # Start the self-destruct process (with confirmation prompt)
|
||||
* $ wp activitypub self-destruct
|
||||
*
|
||||
* # Check the status of an ongoing self-destruct process
|
||||
* $ wp activitypub self-destruct --status
|
||||
*
|
||||
* # Force deletion without confirmation (dangerous!)
|
||||
* $ wp activitypub self-destruct --yes
|
||||
*
|
||||
* ## WHAT THIS DOES
|
||||
*
|
||||
* - Finds all users with ActivityPub capabilities
|
||||
* - Creates Delete activities for each user
|
||||
* - Sends these activities to all followers
|
||||
* - Removes your blog from ActivityPub discovery
|
||||
* - Sets a flag to track completion status
|
||||
*
|
||||
* ## IMPORTANT NOTES
|
||||
*
|
||||
* - This action cannot be undone
|
||||
* - Keep the ActivityPub plugin active during the process
|
||||
* - The process may take several minutes to complete
|
||||
* - You will be notified when the process finishes
|
||||
*
|
||||
* @param array $args The positional arguments (unused).
|
||||
* @param array $assoc_args The associative arguments (--status, --yes).
|
||||
*/
|
||||
public function __invoke( $args, $assoc_args = array() ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
|
||||
// Check if --status flag is provided.
|
||||
if ( isset( $assoc_args['status'] ) ) {
|
||||
$this->show_self_destruct_status();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if self-destruct has already been run.
|
||||
if ( \get_option( 'activitypub_self_destruct' ) ) {
|
||||
\WP_CLI::error( 'Self-destruct has already been initiated. The process may still be running or has completed.' . PHP_EOL . \WP_CLI::colorize( 'To check the status, run: %Bwp activitypub self-destruct --status%n' ) );
|
||||
return;
|
||||
}
|
||||
|
||||
$this->execute_self_destruct( $assoc_args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the self-destruct process.
|
||||
*
|
||||
* This method handles the actual deletion process:
|
||||
* 1. Displays warning and confirmation prompt
|
||||
* 2. Retrieves all ActivityPub-capable users
|
||||
* 3. Creates and schedules Delete activities for each user
|
||||
* 4. Sets the self-destruct flag for status tracking
|
||||
* 5. Provides progress feedback and completion instructions
|
||||
*
|
||||
* @param array $assoc_args The associative arguments from WP-CLI.
|
||||
*/
|
||||
private function execute_self_destruct( $assoc_args ) {
|
||||
$this->display_self_destruct_warning();
|
||||
\WP_CLI::confirm( 'Are you absolutely sure you want to continue?', $assoc_args );
|
||||
|
||||
$user_ids = $this->get_activitypub_users();
|
||||
if ( empty( $user_ids ) ) {
|
||||
\WP_CLI::warning( 'No ActivityPub users found. Nothing to delete.' );
|
||||
return;
|
||||
}
|
||||
|
||||
$processed = $this->process_user_deletions( $user_ids );
|
||||
|
||||
// Delete all remote posts.
|
||||
$deleted_posts = Remote_Posts::delete_all();
|
||||
if ( $deleted_posts > 0 ) {
|
||||
\WP_CLI::line( \WP_CLI::colorize( "%G✓%n Deleted {$deleted_posts} remote post(s)." ) );
|
||||
}
|
||||
|
||||
$this->display_completion_message( $processed );
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the self-destruct warning message.
|
||||
*/
|
||||
private function display_self_destruct_warning() {
|
||||
\WP_CLI::line( \WP_CLI::colorize( '%R⚠️ DESTRUCTIVE OPERATION ⚠️%n' ) );
|
||||
\WP_CLI::line( '' );
|
||||
|
||||
$question = 'You are about to delete your blog from the Fediverse. This action is IRREVERSIBLE and will:';
|
||||
\WP_CLI::line( \WP_CLI::colorize( "%y{$question}%n" ) );
|
||||
\WP_CLI::line( \WP_CLI::colorize( '%y• Send Delete activities to all followers%n' ) );
|
||||
\WP_CLI::line( \WP_CLI::colorize( '%y• Remove your blog from ActivityPub networks%n' ) );
|
||||
\WP_CLI::line( \WP_CLI::colorize( '%y• Delete all cached remote posts%n' ) );
|
||||
\WP_CLI::line( '' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all users with ActivityPub capabilities.
|
||||
*
|
||||
* @return array Array of user IDs with ActivityPub capabilities.
|
||||
*/
|
||||
private function get_activitypub_users() {
|
||||
return \get_users(
|
||||
array(
|
||||
'fields' => 'ID',
|
||||
'capability__in' => array( 'activitypub' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process user deletions and create Delete activities.
|
||||
*
|
||||
* @param array $user_ids Array of user IDs to process.
|
||||
*
|
||||
* @return int Number of users successfully processed.
|
||||
*/
|
||||
private function process_user_deletions( $user_ids ) {
|
||||
$user_count = \count( $user_ids );
|
||||
\WP_CLI::line( \WP_CLI::colorize( '%GStarting Fediverse deletion process...%n' ) );
|
||||
\WP_CLI::line( \WP_CLI::colorize( "%BFound {$user_count} ActivityPub user(s) to process:%n" ) );
|
||||
\WP_CLI::line( '' );
|
||||
|
||||
// Set the self-destruct flag.
|
||||
\update_option( 'activitypub_self_destruct', true );
|
||||
|
||||
$processed = 0;
|
||||
foreach ( $user_ids as $user_id ) {
|
||||
if ( $this->create_delete_activity_for_user( $user_id, $processed, $user_count ) ) {
|
||||
++$processed;
|
||||
}
|
||||
}
|
||||
|
||||
\WP_CLI::line( '' );
|
||||
|
||||
if ( 0 === $processed ) {
|
||||
\WP_CLI::error( 'Failed to schedule any deletions. Please check your configuration.' );
|
||||
}
|
||||
|
||||
return $processed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Delete activity for a specific user.
|
||||
*
|
||||
* @param int $user_id The user ID to process.
|
||||
* @param int $processed Number of users already processed.
|
||||
* @param int $user_count Total number of users to process.
|
||||
*
|
||||
* @return bool True if the activity was created successfully, false otherwise.
|
||||
*/
|
||||
private function create_delete_activity_for_user( $user_id, $processed, $user_count ) {
|
||||
$actor = Actors::get_by_id( $user_id );
|
||||
|
||||
if ( ! $actor ) {
|
||||
\WP_CLI::line( \WP_CLI::colorize( "%R✗ Failed to load user ID: {$user_id}%n" ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
$activity = new Activity();
|
||||
$activity->set_actor( $actor->get_id() );
|
||||
$activity->set_object( $actor->get_id() );
|
||||
$activity->set_type( 'Delete' );
|
||||
|
||||
$result = add_to_outbox( $activity, null, $user_id );
|
||||
if ( \is_wp_error( $result ) ) {
|
||||
\WP_CLI::line( \WP_CLI::colorize( "%R✗ Failed to schedule deletion for: %B{$actor->get_name()}%n - {$result->get_error_message()}" ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
$current = $processed + 1;
|
||||
\WP_CLI::line( \WP_CLI::colorize( "%G✓%n [{$current}/{$user_count}] Scheduled deletion for: %B{$actor->get_name()}%n" ) );
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the completion message after processing.
|
||||
*
|
||||
* @param int $processed Number of users successfully processed.
|
||||
*/
|
||||
private function display_completion_message( $processed ) {
|
||||
if ( 0 === $processed ) {
|
||||
return; // Error already displayed in process_user_deletions.
|
||||
}
|
||||
|
||||
\WP_CLI::success( "Successfully scheduled {$processed} user(s) for Fediverse deletion." );
|
||||
\WP_CLI::line( '' );
|
||||
\WP_CLI::line( \WP_CLI::colorize( '%Y📋 Next Steps:%n' ) );
|
||||
\WP_CLI::line( \WP_CLI::colorize( '%Y• Keep the ActivityPub plugin active%n' ) );
|
||||
\WP_CLI::line( \WP_CLI::colorize( '%Y• Delete activities will be sent automatically%n' ) );
|
||||
\WP_CLI::line( \WP_CLI::colorize( '%Y• Process may take several minutes to complete%n' ) );
|
||||
\WP_CLI::line( \WP_CLI::colorize( '%Y• The plugin will notify you when the process is done.%n' ) );
|
||||
\WP_CLI::line( '' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the status of the self-destruct process.
|
||||
*
|
||||
* Checks the current state of the self-destruct process by:
|
||||
* - Verifying if the process has been initiated
|
||||
* - Counting remaining pending Delete activities
|
||||
* - Displaying appropriate status messages and progress
|
||||
* - Providing guidance on next steps
|
||||
*
|
||||
* Status can be:
|
||||
* - NOT STARTED: Process hasn't been initiated
|
||||
* - IN PROGRESS: Delete activities are still being processed
|
||||
* - COMPLETED: All Delete activities have been sent
|
||||
*/
|
||||
private function show_self_destruct_status() {
|
||||
// Only proceed if self-destruct is active.
|
||||
if ( ! \get_option( 'activitypub_self_destruct', false ) ) {
|
||||
\WP_CLI::line( \WP_CLI::colorize( '%C❌ Status: NOT STARTED%n' ) );
|
||||
\WP_CLI::line( \WP_CLI::colorize( '%CThe self-destruct process has not been initiated.%n' ) );
|
||||
\WP_CLI::line( '' );
|
||||
\WP_CLI::line( \WP_CLI::colorize( '%CTo start the process, run:%n %Bwp activitypub self-destruct%n' ) );
|
||||
\WP_CLI::line( '' );
|
||||
return;
|
||||
}
|
||||
|
||||
\WP_CLI::line( \WP_CLI::colorize( '%B🔍 Self-Destruct Status Check%n' ) );
|
||||
\WP_CLI::line( '' );
|
||||
|
||||
// Check if there are any more pending Delete activities for self-destruct.
|
||||
$pending_deletes = \get_posts(
|
||||
array(
|
||||
'post_type' => Outbox::POST_TYPE,
|
||||
'post_status' => 'pending',
|
||||
'posts_per_page' => -1,
|
||||
'fields' => 'ids',
|
||||
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
|
||||
'meta_query' => array(
|
||||
array(
|
||||
'key' => '_activitypub_activity_type',
|
||||
'value' => 'Delete',
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
// Get count of pending Delete activities.
|
||||
$pending_count = count( $pending_deletes );
|
||||
|
||||
// If no more pending Delete activities, self-destruct is complete.
|
||||
if ( 0 === $pending_count ) {
|
||||
\WP_CLI::line( \WP_CLI::colorize( '%G✅ Status: COMPLETED%n' ) );
|
||||
\WP_CLI::line( \WP_CLI::colorize( '%GYour blog has been successfully removed from the Fediverse.%n' ) );
|
||||
\WP_CLI::line( '' );
|
||||
\WP_CLI::line( \WP_CLI::colorize( '%Y📋 What happened:%n' ) );
|
||||
\WP_CLI::line( \WP_CLI::colorize( '%Y• Delete activities were sent to all followers%n' ) );
|
||||
\WP_CLI::line( \WP_CLI::colorize( '%Y• Your blog is no longer discoverable on ActivityPub networks%n' ) );
|
||||
\WP_CLI::line( \WP_CLI::colorize( '%Y• The self-destruct process has finished%n' ) );
|
||||
} else {
|
||||
\WP_CLI::line( \WP_CLI::colorize( '%Y⏳ Status: IN PROGRESS%n' ) );
|
||||
\WP_CLI::line( \WP_CLI::colorize( '%YThe self-destruct process is currently running.%n' ) );
|
||||
\WP_CLI::line( '' );
|
||||
|
||||
\WP_CLI::line( \WP_CLI::colorize( "%YProgress: {$pending_count} Delete Activities still pending%n" ) );
|
||||
|
||||
\WP_CLI::line( '' );
|
||||
\WP_CLI::line( \WP_CLI::colorize( '%YNote: The process may take several minutes to complete.%n' ) );
|
||||
}
|
||||
|
||||
\WP_CLI::line( '' );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user