WordPress.org

Make WordPress Core

Ticket #43738: 43738.diff

File 43738.diff, 13.1 KB (added by pbiron, 19 months ago)

preliminary! adds just the network-level UI; does not actually handle network-level exports/erases.

  • src/wp-admin/erase-personal-data.php

    From aba945444eff7308957b642d17e40bda7ff72ae8 Mon Sep 17 00:00:00 2001
    From: Paul Biron <paul@sparrowhawkcomputing.com>
    Date: Thu, 2 Apr 2020 13:22:18 -0600
    Subject: [PATCH] Add UI for managing requests at the network-level.
    
    ---
     src/wp-admin/erase-personal-data.php          |  2 +-
     src/wp-admin/export-personal-data.php         |  2 +-
     .../class-wp-privacy-requests-table.php       | 22 ++++++++
     src/wp-admin/includes/privacy-tools.php       | 53 ++++++++++++++-----
     src/wp-admin/network/erase-personal-data.php  | 12 +++++
     src/wp-admin/network/export-personal-data.php | 12 +++++
     src/wp-admin/network/menu.php                 |  5 ++
     src/wp-includes/admin-bar.php                 | 11 ++++
     src/wp-includes/class-wp-user-request.php     | 14 +++++
     src/wp-includes/user.php                      | 46 ++++++++++++----
     10 files changed, 153 insertions(+), 26 deletions(-)
     create mode 100644 src/wp-admin/network/erase-personal-data.php
     create mode 100644 src/wp-admin/network/export-personal-data.php
    
    diff --git a/src/wp-admin/erase-personal-data.php b/src/wp-admin/erase-personal-data.php
    index d674633f0f..08601d9b7f 100644
    a b require_once ABSPATH . 'wp-admin/admin-header.php'; 
    5656
    5757        <?php settings_errors(); ?>
    5858
    59         <form action="<?php echo esc_url( admin_url( 'erase-personal-data.php' ) ); ?>" method="post" class="wp-privacy-request-form">
     59        <form action="<?php echo esc_url( self_admin_url( 'erase-personal-data.php' ) ); ?>" method="post" class="wp-privacy-request-form">
    6060                <h2><?php esc_html_e( 'Add Data Erasure Request' ); ?></h2>
    6161                <p><?php esc_html_e( 'An email will be sent to the user at this email address asking them to verify the request.' ); ?></p>
    6262
  • src/wp-admin/export-personal-data.php

    diff --git a/src/wp-admin/export-personal-data.php b/src/wp-admin/export-personal-data.php
    index 8e44345a99..bea49bccf8 100644
    a b require_once ABSPATH . 'wp-admin/admin-header.php'; 
    5656
    5757        <?php settings_errors(); ?>
    5858
    59         <form action="<?php echo esc_url( admin_url( 'export-personal-data.php' ) ); ?>" method="post" class="wp-privacy-request-form">
     59        <form action="<?php echo esc_url( self_admin_url( 'export-personal-data.php' ) ); ?>" method="post" class="wp-privacy-request-form">
    6060                <h2><?php esc_html_e( 'Add Data Export Request' ); ?></h2>
    6161                <p><?php esc_html_e( 'An email will be sent to the user at this email address asking them to verify the request.' ); ?></p>
    6262
  • src/wp-admin/includes/class-wp-privacy-requests-table.php

    diff --git a/src/wp-admin/includes/class-wp-privacy-requests-table.php b/src/wp-admin/includes/class-wp-privacy-requests-table.php
    index 23c31b1f31..4302a7af91 100644
    a b abstract class WP_Privacy_Requests_Table extends WP_List_Table { 
    279279                        'post_status'    => 'any',
    280280                        's'              => isset( $_REQUEST['s'] ) ? sanitize_text_field( $_REQUEST['s'] ) : '',
    281281                );
     282                if ( is_network_admin() ) {
     283                        $args['meta_query'] = array(
     284                                array(
     285                                        'key'   => '_wp_user_request_blog_id',
     286                                        'value' => 0,
     287                                ),
     288                        );
     289                }
     290                else {
     291                        $args['meta_query'] = array(
     292                                'relation' => 'OR',
     293                                array(
     294                                        'key'     => '_wp_user_request_blog_id',
     295                                        'value'   => get_current_blog_id(),
     296                                ),
     297                                // The meta key will not exist for requests submitted before 5.5.
     298                                array(
     299                                        'key'     => '_wp_user_request_blog_id',
     300                                        'compare' => 'NOT EXISTS',
     301                                ),
     302                        );
     303                }
    282304
    283305                $orderby_mapping = array(
    284306                        'requester' => 'post_title',
  • src/wp-admin/includes/privacy-tools.php

    diff --git a/src/wp-admin/includes/privacy-tools.php b/src/wp-admin/includes/privacy-tools.php
    index 2d35984499..50ab29e9e3 100644
    a b function _wp_personal_data_handle_actions() { 
    141141                                        break;
    142142                                }
    143143
    144                                 $request_id = wp_create_user_request( $email_address, $action_type );
     144                                $request_id = wp_create_user_request(
     145                                        $email_address,
     146                                        $action_type,
     147                                        array(),
     148                                        is_network_admin() ? 0 : get_current_blog_id()
     149                                );
    145150
    146151                                if ( is_wp_error( $request_id ) ) {
    147152                                        add_settings_error(
    function _wp_personal_data_cleanup_requests() { 
    184189        /** This filter is documented in wp-includes/user.php */
    185190        $expires = (int) apply_filters( 'user_request_key_expiration', DAY_IN_SECONDS );
    186191
    187         $requests_query = new WP_Query(
    188                 array(
    189                         'post_type'      => 'user_request',
    190                         'posts_per_page' => -1,
    191                         'post_status'    => 'request-pending',
    192                         'fields'         => 'ids',
    193                         'date_query'     => array(
    194                                 array(
    195                                         'column' => 'post_modified_gmt',
    196                                         'before' => $expires . ' seconds ago',
    197                                 ),
     192        $args = array(
     193                'post_type'      => 'user_request',
     194                'posts_per_page' => -1,
     195                'post_status'    => 'request-pending',
     196                'fields'         => 'ids',
     197                'date_query'     => array(
     198                        array(
     199                                'column' => 'post_modified_gmt',
     200                                'before' => $expires . ' seconds ago',
    198201                        ),
    199                 )
     202                ),
    200203        );
     204        if ( is_network_admin() ) {
     205                $args['meta_query'] = array(
     206                        array(
     207                                'key'   => '_wp_user_request_blog_id',
     208                                'value' => 0,
     209                        ),
     210                );
     211        }
     212        else {
     213                $args['meta_query'] = array(
     214                        'relation' => 'OR',
     215                        array(
     216                                'key'     => '_wp_user_request_blog_id',
     217                                'value'   => get_current_blog_id(),
     218                        ),
     219                        // The meta key will not exist for requests submitted before 5.5.
     220                        array(
     221                                'key'     => '_wp_user_request_blog_id',
     222                                'compare' => 'NOT EXISTS',
     223                        ),
     224                );
     225        }
     226
     227        $requests_query = new WP_Query( $args );
    201228
    202229        $request_ids = $requests_query->posts;
    203230
  • new file src/wp-admin/network/erase-personal-data.php

    diff --git a/src/wp-admin/network/erase-personal-data.php b/src/wp-admin/network/erase-personal-data.php
    new file mode 100644
    index 0000000000..30b1d5446b
    - +  
     1<?php
     2/**
     3 * Privacy tools, Erase Personal Data screen.
     4 *
     5 * @package WordPress
     6 * @subpackage Administration
     7 */
     8
     9/** Load WordPress Administration Bootstrap */
     10require_once __DIR__ . '/admin.php';
     11
     12require ABSPATH . 'wp-admin/erase-personal-data.php';
  • new file src/wp-admin/network/export-personal-data.php

    diff --git a/src/wp-admin/network/export-personal-data.php b/src/wp-admin/network/export-personal-data.php
    new file mode 100644
    index 0000000000..12a46152b1
    - +  
     1<?php
     2/**
     3 * Privacy tools, Export Personal Data screen.
     4 *
     5 * @package WordPress
     6 * @subpackage Administration
     7 */
     8
     9/** Load WordPress Administration Bootstrap */
     10require_once __DIR__ . '/admin.php';
     11
     12require ABSPATH . 'wp-admin/export-personal-data.php';
  • src/wp-admin/network/menu.php

    diff --git a/src/wp-admin/network/menu.php b/src/wp-admin/network/menu.php
    index 28509b1769..de2029d7ef 100644
    a b $submenu['plugins.php'][5] = array( __( 'Installed Plugins' ), 'manage_network_ 
    106106$submenu['plugins.php'][10] = array( _x( 'Add New', 'plugin' ), 'install_plugins', 'plugin-install.php' );
    107107$submenu['plugins.php'][15] = array( __( 'Plugin Editor' ), 'edit_plugins', 'plugin-editor.php' );
    108108
     109$menu[21]                 = array( __( 'Tools' ), 'edit_posts', 'tools.php', '', 'menu-top menu-icon-tools', 'menu-tools', 'dashicons-admin-tools' );
     110$submenu['tools.php'][5]  = array( __( 'Available Tools' ), 'edit_posts', 'tools.php' );
     111$submenu['tools.php'][25] = array( __( 'Export Personal Data' ), 'export_others_personal_data', 'export-personal-data.php' );
     112$submenu['tools.php'][30] = array( __( 'Erase Personal Data' ), 'erase_others_personal_data', 'erase-personal-data.php' );
     113
    109114$menu[25] = array( __( 'Settings' ), 'manage_network_options', 'settings.php', '', 'menu-top menu-icon-settings', 'menu-settings', 'dashicons-admin-settings' );
    110115if ( defined( 'MULTISITE' ) && defined( 'WP_ALLOW_MULTISITE' ) && WP_ALLOW_MULTISITE ) {
    111116        $submenu['settings.php'][5]  = array( __( 'Network Settings' ), 'manage_network_options', 'settings.php' );
  • src/wp-includes/admin-bar.php

    diff --git a/src/wp-includes/admin-bar.php b/src/wp-includes/admin-bar.php
    index 753e5ab5be..4dbcdad4a1 100644
    a b function wp_admin_bar_my_sites_menu( $wp_admin_bar ) { 
    556556                        );
    557557                }
    558558
     559                if ( current_user_can( 'edit_posts' ) ) {
     560                        $wp_admin_bar->add_node(
     561                                array(
     562                                        'parent' => 'network-admin',
     563                                        'id'     => 'network-admin-tools',
     564                                        'title'  => __( 'Tools' ),
     565                                        'href'   => network_admin_url( 'tools.php' ),
     566                                )
     567                        );
     568                }
     569
    559570                if ( current_user_can( 'manage_network_options' ) ) {
    560571                        $wp_admin_bar->add_node(
    561572                                array(
  • src/wp-includes/class-wp-user-request.php

    diff --git a/src/wp-includes/class-wp-user-request.php b/src/wp-includes/class-wp-user-request.php
    index 7e445cfa63..8935b30f25 100644
    a b final class WP_User_Request { 
    9595         */
    9696        public $confirm_key = '';
    9797
     98        /**
     99         * Blog ID the request was submitted to.
     100         *
     101         * Will be 0 if the request was submitted at the network-level.
     102         *
     103         * @since 5.5
     104         * @var int
     105         */
     106        public $blog_id;
     107
    98108        /**
    99109         * Constructor.
    100110         *
    final class WP_User_Request { 
    114124                $this->completed_timestamp = (int) get_post_meta( $post->ID, '_wp_user_request_completed_timestamp', true );
    115125                $this->request_data        = json_decode( $post->post_content, true );
    116126                $this->confirm_key         = $post->post_password;
     127
     128                $blog_id                   = get_post_meta( $post->ID, '_wp_user_request_blog_id', true );
     129                // $blog_id will be the empty string for requests submitted prior to 5.5.
     130                $this->blog_id             = '' !== $blog_id ? (int) $blog_id : get_current_blog_id();
    117131        }
    118132}
  • src/wp-includes/user.php

    diff --git a/src/wp-includes/user.php b/src/wp-includes/user.php
    index f0cc8c33bd..ddb0e2e050 100644
    a b function _wp_privacy_account_request_confirmed_message( $request_id ) { 
    35543554 * users on the site, or guests without a user account.
    35553555 *
    35563556 * @since 4.9.6
     3557 * @since 5.5.0 Added `$blog_id` parameter.
    35573558 *
    35583559 * @param string $email_address User email address. This can be the address of a registered or non-registered user.
    35593560 * @param string $action_name   Name of the action that is being confirmed. Required.
    35603561 * @param array  $request_data  Misc data you want to send with the verification request and pass to the actions once the request is confirmed.
     3562 * @param int|null $blog_id     Blog ID to create request in.  Use 0 for a network-level requests.  Default is null, indicating the current blog ID.
    35613563 * @return int|WP_Error Returns the request ID if successful, or a WP_Error object on failure.
    35623564 */
    3563 function wp_create_user_request( $email_address = '', $action_name = '', $request_data = array() ) {
     3565function wp_create_user_request( $email_address = '', $action_name = '', $request_data = array(), $blog_id = null ) {
    35643566        $email_address = sanitize_email( $email_address );
    35653567        $action_name   = sanitize_key( $action_name );
     3568        $blog_id       = null === $blog_id ? get_current_blog_id() : (int) $blog_id;
    35663569
    35673570        if ( ! is_email( $email_address ) ) {
    35683571                return new WP_Error( 'invalid_email', __( 'Invalid email address.' ) );
    function wp_create_user_request( $email_address = '', $action_name = '', $reques 
    35723575                return new WP_Error( 'invalid_action', __( 'Invalid action name.' ) );
    35733576        }
    35743577
     3578        if ( $blog_id && ! get_site( $blog_id ) ) {
     3579                return new WP_Error( 'invalid_blog_id', __( 'Invalid blog ID.' ) );
     3580        }
     3581
    35753582        $user    = get_user_by( 'email', $email_address );
    35763583        $user_id = $user && ! is_wp_error( $user ) ? $user->ID : 0;
    35773584
    35783585        // Check for duplicates.
    3579         $requests_query = new WP_Query(
    3580                 array(
    3581                         'post_type'     => 'user_request',
    3582                         'post_name__in' => array( $action_name ), // Action name stored in post_name column.
    3583                         'title'         => $email_address,        // Email address stored in post_title column.
    3584                         'post_status'   => array(
    3585                                 'request-pending',
    3586                                 'request-confirmed',
     3586        $args = array(
     3587                'post_type'     => 'user_request',
     3588                'post_name__in' => array( $action_name ), // Action name stored in post_name column.
     3589                'title'         => $email_address,        // Email address stored in post_title column.
     3590                'post_status'   => array(
     3591                        'request-pending',
     3592                        'request-confirmed',
     3593                ),
     3594                'fields'        => 'ids',
     3595                'meta_query'    => array(
     3596                        array(
     3597                                'key'   => '_wp_user_request_blog_id',
     3598                                'value' => $blog_id,
    35873599                        ),
    3588                         'fields'        => 'ids',
    3589                 )
     3600                ),
    35903601        );
     3602        if ( $blog_id ) {
     3603                // add a check for requests submitted prior to 5.5.
     3604                $args['meta_query']['relation'] = 'OR';
     3605                $args['meta_query'][] = array(
     3606                        'key'     => '_wp_user_request_blog_id',
     3607                        'compare' => 'NOT EXISTS',
     3608                );
     3609        }
     3610
     3611        $requests_query = new WP_Query( $args );
    35913612
    35923613        if ( $requests_query->found_posts ) {
    35933614                return new WP_Error( 'duplicate_request', __( 'An incomplete request for this email address already exists.' ) );
    function wp_create_user_request( $email_address = '', $action_name = '', $reques 
    36033624                        'post_type'     => 'user_request',
    36043625                        'post_date'     => current_time( 'mysql', false ),
    36053626                        'post_date_gmt' => current_time( 'mysql', true ),
     3627                        'meta_input'    => array(
     3628                                '_wp_user_request_blog_id' => $blog_id,
     3629                        ),
    36063630                ),
    36073631                true
    36083632        );