Source
File: wp-admin/includes/ajax-actions.php
function wp_ajax_wp_privacy_erase_personal_data() {
if ( empty( $_POST['id'] ) ) {
wp_send_json_error( __( 'Missing request ID.' ) );
}
$request_id = (int) $_POST['id'];
if ( $request_id < 1 ) {
wp_send_json_error( __( 'Invalid request ID.' ) );
}
// Both capabilities are required to avoid confusion, see `_wp_personal_data_removal_page()`.
if ( ! current_user_can( 'erase_others_personal_data' ) || ! current_user_can( 'delete_users' ) ) {
wp_send_json_error( __( 'Sorry, you are not allowed to perform this action.' ) );
}
check_ajax_referer( 'wp-privacy-erase-personal-data-' . $request_id, 'security' );
// Get the request.
$request = wp_get_user_request( $request_id );
if ( ! $request || 'remove_personal_data' !== $request->action_name ) {
wp_send_json_error( __( 'Invalid request type.' ) );
}
$email_address = $request->email;
if ( ! is_email( $email_address ) ) {
wp_send_json_error( __( 'Invalid email address in request.' ) );
}
if ( ! isset( $_POST['eraser'] ) ) {
wp_send_json_error( __( 'Missing eraser index.' ) );
}
$eraser_index = (int) $_POST['eraser'];
if ( ! isset( $_POST['page'] ) ) {
wp_send_json_error( __( 'Missing page index.' ) );
}
$page = (int) $_POST['page'];
/**
* Filters the array of personal data eraser callbacks.
*
* @since 4.9.6
*
* @param array $args {
* An array of callable erasers of personal data. Default empty array.
*
* @type array ...$0 {
* Array of personal data exporters.
*
* @type callable $callback Callable eraser that accepts an email address and
* a page and returns an array with boolean values for
* whether items were removed or retained and any messages
* from the eraser, as well as if additional pages are
* available.
* @type string $exporter_friendly_name Translated user facing friendly name for the eraser.
* }
* }
*/
$erasers = apply_filters( 'wp_privacy_personal_data_erasers', array() );
// Do we have any registered erasers?
if ( 0 < count( $erasers ) ) {
if ( $eraser_index < 1 ) {
wp_send_json_error( __( 'Eraser index cannot be less than one.' ) );
}
if ( $eraser_index > count( $erasers ) ) {
wp_send_json_error( __( 'Eraser index is out of range.' ) );
}
if ( $page < 1 ) {
wp_send_json_error( __( 'Page index cannot be less than one.' ) );
}
$eraser_keys = array_keys( $erasers );
$eraser_key = $eraser_keys[ $eraser_index - 1 ];
$eraser = $erasers[ $eraser_key ];
if ( ! is_array( $eraser ) ) {
/* translators: %d: Eraser array index. */
wp_send_json_error( sprintf( __( 'Expected an array describing the eraser at index %d.' ), $eraser_index ) );
}
if ( ! array_key_exists( 'eraser_friendly_name', $eraser ) ) {
/* translators: %d: Eraser array index. */
wp_send_json_error( sprintf( __( 'Eraser array at index %d does not include a friendly name.' ), $eraser_index ) );
}
$eraser_friendly_name = $eraser['eraser_friendly_name'];
if ( ! array_key_exists( 'callback', $eraser ) ) {
wp_send_json_error(
sprintf(
/* translators: %s: Eraser friendly name. */
__( 'Eraser does not include a callback: %s.' ),
esc_html( $eraser_friendly_name )
)
);
}
if ( ! is_callable( $eraser['callback'] ) ) {
wp_send_json_error(
sprintf(
/* translators: %s: Eraser friendly name. */
__( 'Eraser callback is not valid: %s.' ),
esc_html( $eraser_friendly_name )
)
);
}
$callback = $eraser['callback'];
$response = call_user_func( $callback, $email_address, $page );
if ( is_wp_error( $response ) ) {
wp_send_json_error( $response );
}
if ( ! is_array( $response ) ) {
wp_send_json_error(
sprintf(
/* translators: 1: Eraser friendly name, 2: Eraser array index. */
__( 'Did not receive array from %1$s eraser (index %2$d).' ),
esc_html( $eraser_friendly_name ),
$eraser_index
)
);
}
if ( ! array_key_exists( 'items_removed', $response ) ) {
wp_send_json_error(
sprintf(
/* translators: 1: Eraser friendly name, 2: Eraser array index. */
__( 'Expected items_removed key in response array from %1$s eraser (index %2$d).' ),
esc_html( $eraser_friendly_name ),
$eraser_index
)
);
}
if ( ! array_key_exists( 'items_retained', $response ) ) {
wp_send_json_error(
sprintf(
/* translators: 1: Eraser friendly name, 2: Eraser array index. */
__( 'Expected items_retained key in response array from %1$s eraser (index %2$d).' ),
esc_html( $eraser_friendly_name ),
$eraser_index
)
);
}
if ( ! array_key_exists( 'messages', $response ) ) {
wp_send_json_error(
sprintf(
/* translators: 1: Eraser friendly name, 2: Eraser array index. */
__( 'Expected messages key in response array from %1$s eraser (index %2$d).' ),
esc_html( $eraser_friendly_name ),
$eraser_index
)
);
}
if ( ! is_array( $response['messages'] ) ) {
wp_send_json_error(
sprintf(
/* translators: 1: Eraser friendly name, 2: Eraser array index. */
__( 'Expected messages key to reference an array in response array from %1$s eraser (index %2$d).' ),
esc_html( $eraser_friendly_name ),
$eraser_index
)
);
}
if ( ! array_key_exists( 'done', $response ) ) {
wp_send_json_error(
sprintf(
/* translators: 1: Eraser friendly name, 2: Eraser array index. */
__( 'Expected done flag in response array from %1$s eraser (index %2$d).' ),
esc_html( $eraser_friendly_name ),
$eraser_index
)
);
}
} else {
// No erasers, so we're done.
$eraser_key = '';
$response = array(
'items_removed' => false,
'items_retained' => false,
'messages' => array(),
'done' => true,
);
}
/**
* Filters a page of personal data eraser data.
*
* Allows the erasure response to be consumed by destinations in addition to Ajax.
*
* @since 4.9.6
*
* @param array $response The personal data for the given exporter and page.
* @param int $eraser_index The index of the eraser that provided this data.
* @param string $email_address The email address associated with this personal data.
* @param int $page The page for this response.
* @param int $request_id The privacy request post ID associated with this request.
* @param string $eraser_key The key (slug) of the eraser that provided this data.
*/
$response = apply_filters( 'wp_privacy_personal_data_erasure_page', $response, $eraser_index, $email_address, $page, $request_id, $eraser_key );
if ( is_wp_error( $response ) ) {
wp_send_json_error( $response );
}
wp_send_json_success( $response );
}