';
echo '
' . \esc_html__( 'Import a domain blocklist to block multiple ActivityPub instances at once. Supported formats:', 'activitypub' ) . '
';
echo '
';
echo '- ' . \esc_html__( 'Mastodon CSV export (with #domain header)', 'activitypub' ) . '
';
echo '- ' . \esc_html__( 'Simple text file with one domain per line', 'activitypub' ) . '
';
echo '
';
// File upload option.
\printf( '
%s
', \esc_html__( 'Option 1: Upload a File', 'activitypub' ) );
\wp_import_upload_form( 'admin.php?import=blocklist&step=1' );
// URL import option.
\printf( '
%s
', \esc_html__( 'Option 2: Import from URL', 'activitypub' ) );
?>
';
}
/**
* Handle file upload and import.
*
* @return void
*/
private static function handle_upload() {
$error_message = \__( 'Sorry, there has been an error.', 'activitypub' );
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified in dispatch().
if ( ! isset( $_FILES['import']['name'] ) ) {
echo '
' . \esc_html( $error_message ) . '
';
\printf(
/* translators: 1: php.ini, 2: post_max_size, 3: upload_max_filesize */
\esc_html__( 'File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your %1$s file or by %2$s being defined as smaller than %3$s in %1$s.', 'activitypub' ),
'php.ini',
'post_max_size',
'upload_max_filesize'
);
echo '
';
return;
}
// Allow CSV and TXT files.
$allowed_types = array(
'csv' => 'text/csv',
'txt' => 'text/plain',
);
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified in dispatch().
$file_info = \wp_check_filetype( \sanitize_file_name( $_FILES['import']['name'] ), $allowed_types );
if ( ! $file_info['type'] ) {
\printf(
'
%s
%s
',
\esc_html( $error_message ),
\esc_html__( 'The uploaded file must be a CSV or TXT file. Please try again with the correct file format.', 'activitypub' )
);
return;
}
// phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput -- Nonce verified in dispatch(), tmp_name is a server path.
$file_path = $_FILES['import']['tmp_name'] ?? '';
if ( empty( $file_path ) ) {
\printf( '
%s
%s
', \esc_html( $error_message ), \esc_html__( 'Upload failed. Please try again.', 'activitypub' ) );
return;
}
$domains = self::parse_csv( $file_path );
if ( empty( $domains ) ) {
\printf( '
%s
%s
', \esc_html( $error_message ), \esc_html__( 'No valid domains found in the file.', 'activitypub' ) );
return;
}
self::import( $domains );
}
/**
* Handle URL import.
*
* @return void
*/
private static function handle_url_import() {
$error_message = \__( 'Sorry, there has been an error.', 'activitypub' );
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified in dispatch().
$url = \sanitize_url( \wp_unslash( $_POST['import_url'] ?? '' ) );
if ( empty( $url ) ) {
\printf( '
%s
%s
', \esc_html( $error_message ), \esc_html__( 'Please provide a valid URL.', 'activitypub' ) );
return;
}
if ( ! \filter_var( $url, FILTER_VALIDATE_URL ) ) {
\printf( '
%s
%s
', \esc_html( $error_message ), \esc_html__( 'The provided URL is not valid.', 'activitypub' ) );
return;
}
$result = Blocklist_Subscriptions::sync( $url );
if ( false === $result ) {
\printf( '
%s
%s
', \esc_html( $error_message ), \esc_html__( 'Failed to fetch or parse the blocklist URL.', 'activitypub' ) );
return;
}
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified in dispatch().
$subscribe = ! empty( $_POST['subscribe'] );
// Add subscription if requested (no need to sync again, just did it).
$subscribed = $subscribe && Blocklist_Subscriptions::add( $url );
self::show_url_import_results( $result, $subscribed );
}
/**
* Execute the import for file uploads.
*
* @param array $domains Array of domains to import.
*
* @return void
*/
private static function import( $domains ) {
\set_time_limit( 0 );
/**
* Fires when the blocklist import starts.
*/
\do_action( 'import_start' );
$existing = Moderation::get_site_blocks()[ Moderation::TYPE_DOMAIN ] ?? array();
$new_domains = \array_diff( $domains, $existing );
$imported = \count( $new_domains );
$skipped = \count( $domains ) - $imported;
Moderation::add_site_blocks( Moderation::TYPE_DOMAIN, $new_domains );
/**
* Fires when the blocklist import ends.
*/
\do_action( 'import_end' );
echo '
' . \esc_html__( 'Import Complete', 'activitypub' ) . '
';
\printf(
'
%s
',
\esc_html(
\sprintf(
/* translators: %s: Number of domains */
\_n( 'Imported %s domain.', 'Imported %s domains.', $imported, 'activitypub' ),
\number_format_i18n( $imported )
)
)
);
if ( $skipped > 0 ) {
\printf(
'
%s
',
\esc_html(
\sprintf(
/* translators: %s: Number of domains */
\_n( 'Skipped %s domain (already blocked).', 'Skipped %s domains (already blocked).', $skipped, 'activitypub' ),
\number_format_i18n( $skipped )
)
)
);
}
\printf(
'
%s
',
\esc_url( \admin_url( 'options-general.php?page=activitypub&tab=settings' ) ),
\esc_html__( 'View blocked domains in settings', 'activitypub' )
);
}
/**
* Show results for URL import.
*
* @param int $imported Number of domains imported.
* @param bool $subscribed Whether the URL was subscribed to.
*
* @return void
*/
private static function show_url_import_results( $imported, $subscribed ) {
echo '
' . \esc_html__( 'Import Complete', 'activitypub' ) . '
';
\printf(
'
%s
',
\esc_html(
\sprintf(
/* translators: %s: Number of domains */
\_n( 'Imported %s new domain.', 'Imported %s new domains.', $imported, 'activitypub' ),
\number_format_i18n( $imported )
)
)
);
if ( $subscribed ) {
echo '
' . \esc_html__( 'Subscribed for automatic weekly updates.', 'activitypub' ) . '
';
}
\printf(
'
%s
',
\esc_url( \admin_url( 'options-general.php?page=activitypub&tab=settings' ) ),
\esc_html__( 'View blocked domains in settings', 'activitypub' )
);
}
/**
* Parse a CSV file and extract domain names.
*
* @param string $file_path Path to the CSV file.
* @return array Array of unique, valid domain names.
*/
public static function parse_csv( $file_path ) {
if ( ! \file_exists( $file_path ) || ! \is_readable( $file_path ) ) {
return array();
}
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- Reading local file.
$content = \file_get_contents( $file_path );
if ( false === $content ) {
return array();
}
return Blocklist_Subscriptions::parse_csv_string( $content );
}
}