wp_ajax_wp_privacy_erase_personal_data

The timeline below displays how wordpress function wp_ajax_wp_privacy_erase_personal_data has changed across different WordPress versions. If a version is not listed, refer to the next available version below.

WordPress Version: 6.4

/**
 * Handles erasing personal data via AJAX.
 *
 * @since 4.9.6
 */
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
     *                                                number, 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 number.
     *
     *     @type bool     $items_removed  Whether items were actually removed or not.
     *     @type bool     $items_retained Whether items were retained or not.
     *     @type string[] $messages       An array of messages to add to the personal data export file.
     *     @type bool     $done           Whether the eraser is finished or not.
     * }
     * @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 number 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);
}

WordPress Version: 6.3

/**
 * Handles erasing personal data via AJAX.
 *
 * @since 4.9.6
 */
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);
}

WordPress Version: 5.5

/**
 * Ajax handler for erasing personal data.
 *
 * @since 4.9.6
 */
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);
}

WordPress Version: 5.4

/**
 * Ajax handler for erasing personal data.
 *
 * @since 4.9.6
 */
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 {
     *         Array of personal data exporters.
     *
     *         @type string $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);
}

WordPress Version: 5.3

/**
 * Ajax handler for erasing personal data.
 *
 * @since 4.9.6
 */
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 data.
    $request = wp_get_user_request_data($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 {
     *         Array of personal data exporters.
     *
     *         @type string $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);
}

WordPress Version: 5.2

/**
 * Ajax handler for erasing personal data.
 *
 * @since 4.9.6
 */
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 data.
    $request = wp_get_user_request_data($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 {
     *         Array of personal data exporters.
     *
     *         @type string $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);
}

WordPress Version: .10

/**
 * Ajax handler for erasing personal data.
 *
 * @since 4.9.6
 */
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(__('Invalid request.'));
    }
    check_ajax_referer('wp-privacy-erase-personal-data-' . $request_id, 'security');
    // Get the request data.
    $request = wp_get_user_request_data($request_id);
    if (!$request || 'remove_personal_data' !== $request->action_name) {
        wp_send_json_error(__('Invalid request ID.'));
    }
    $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 {
     *         Array of personal data exporters.
     *
     *         @type string $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: array index */
            wp_send_json_error(sprintf(__('Expected an array describing the eraser at index %d.'), $eraser_index));
        }
        if (!array_key_exists('callback', $eraser)) {
            /* translators: %d: array index */
            wp_send_json_error(sprintf(__('Eraser array at index %d does not include a callback.'), $eraser_index));
        }
        if (!is_callable($eraser['callback'])) {
            /* translators: %d: array index */
            wp_send_json_error(sprintf(__('Eraser callback at index %d is not a valid callback.'), $eraser_index));
        }
        if (!array_key_exists('eraser_friendly_name', $eraser)) {
            /* translators: %d: array index */
            wp_send_json_error(sprintf(__('Eraser array at index %d does not include a friendly name.'), $eraser_index));
        }
        $callback = $eraser['callback'];
        $eraser_friendly_name = $eraser['eraser_friendly_name'];
        $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: 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: 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: 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: 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: 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: 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);
}