Ticket #43438: 43438.2.diff
File 43438.2.diff, 17.8 KB (added by , 7 years ago) |
---|
-
src/wp-admin/admin-ajax.php
129 129 'get-post-thumbnail-html', 130 130 'get-community-events', 131 131 'edit-theme-plugin-file', 132 'wp-privacy-export-personal-data', 132 133 ); 133 134 134 135 // Deprecated -
src/wp-admin/includes/ajax-actions.php
4326 4326 ); 4327 4327 } 4328 4328 } 4329 4330 function wp_ajax_wp_privacy_export_personal_data() { 4331 $email_address = $_POST['email']; 4332 $exporter_index = $_POST['exporter']; 4333 $page = $_POST['page']; 4334 4335 $exporters = apply_filters( 'wp_privacy_personal_data_exporters', array() ); 4336 4337 if ( ! is_email( $email_address ) ) { 4338 wp_send_json_error( 'a valid email address must be given' ); 4339 } 4340 4341 if ( $exporter_index < 0 ) { 4342 wp_send_json_error( 'exporter index cannot be negative' ); 4343 } 4344 4345 if ( $exporter_index > count( $exporters ) - 1 ) { 4346 wp_send_json_error( 'exporter index out of range' ); 4347 } 4348 4349 if ( $page < 0 ) { 4350 wp_send_json_error( 'page index cannot be negative' ); 4351 } 4352 4353 $response = call_user_func( $exporters[ $exporter_index ]['callback'], $email_address, $page ); 4354 4355 wp_send_json_success( $response ); 4356 } -
src/wp-admin/privacy.php
16 16 // "Borrow" xfn.js for now so we don't have to create new files. 17 17 // wp_enqueue_script( 'xfn' ); 18 18 19 $title = __( 'Privacy Tools' ); 20 19 21 $action = isset( $_POST['action'] ) ? $_POST['action'] : ''; 20 22 23 $doing_personal_data_export_for_email = ''; 24 21 25 if ( ! empty( $action ) ) { 22 26 check_admin_referer( $action ); 23 27 … … 24 28 if ( 'set-privacy-page' === $action ) { 25 29 $privacy_policy_page_id = isset( $_POST['page_for_privacy_policy'] ) ? (int) $_POST['page_for_privacy_policy'] : 0; 26 30 update_option( 'wp_page_for_privacy_policy', $privacy_policy_page_id ); 27 28 31 add_settings_error( 29 32 'page_for_privacy_policy', 30 33 'page_for_privacy_policy', … … 57 60 'updated' 58 61 ); 59 62 } 63 } elseif ( 'export-personal-data' === $action ) { 64 $username_or_email_address = isset( $_POST['username_or_email_to_export'] ) ? $_POST['username_or_email_to_export'] : ''; 65 $username_or_email_address = sanitize_text_field( $username_or_email_address ); 66 67 if ( ! is_email( $username_or_email_address ) ) { 68 $user = get_user_by( 'login', $username_or_email_address ); 69 if ( ! $user instanceof WP_User ) { 70 add_settings_error( 71 'username_or_email_to_export', 72 'username_or_email_to_export', 73 __( 'Unable to export personal data. Username not recognized.' ), 74 'error' 75 ); 76 } else { 77 $doing_personal_data_export_for_email = $user->user_email; 78 } 79 } else { 80 $doing_personal_data_export_for_email = $username_or_email_address; 81 } 82 83 if ( ! empty( $doing_personal_data_export_for_email ) ) { 84 $title = __( 'Export Personal Data' ); 85 } 60 86 } 61 87 } 62 88 63 // If a privacy policy page ID is available, make sure the page actually exists. If not, display a warning 64 $privacy_policy_page_exists = false; 65 $privacy_policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' ); 89 if ( empty( $doing_personal_data_export_for_email ) ) { 90 // If a privacy policy page ID is available, make sure the page actually exists. If not, display a warning 91 $privacy_policy_page_exists = false; 92 $privacy_policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' ); 66 93 67 if ( ! empty( $privacy_policy_page_id ) ) { 68 $privacy_policy_page = get_post( $privacy_policy_page_id ); 69 if ( ! $privacy_policy_page instanceof WP_Post ) { 70 add_settings_error( 71 'page_for_privacy_policy', 72 'page_for_privacy_policy', 73 __( 'The currently selected privacy policy page does not exist. Please create or select new page.' ), 74 'warning' 75 ); 76 } else { 77 if ( 'trash' === $privacy_policy_page->post_status ) { 94 if ( ! empty( $privacy_policy_page_id ) ) { 95 $privacy_policy_page = get_post( $privacy_policy_page_id ); 96 if ( ! $privacy_policy_page instanceof WP_Post ) { 78 97 add_settings_error( 79 98 'page_for_privacy_policy', 80 99 'page_for_privacy_policy', 81 sprintf( 82 __( 'The currently selected privacy policy page is in the trash. Please create or select new privacy policy page or <a href="%s">restore the current page</a>.' ), 83 'edit.php?post_status=trash&post_type=page' 84 ), 85 'error' 100 __( 'The currently selected privacy policy page does not exist. Please create or select new page.' ), 101 'warning' 86 102 ); 87 103 } else { 88 $privacy_policy_page_exists = true; 104 if ( 'trash' === $privacy_policy_page->post_status ) { 105 add_settings_error( 106 'page_for_privacy_policy', 107 'page_for_privacy_policy', 108 sprintf( 109 __( 'The currently selected privacy policy page is in the trash. Please create or select new privacy policy page or <a href="%s">restore the current page</a>.' ), 110 'edit.php?post_status=trash&post_type=page' 111 ), 112 'error' 113 ); 114 } else { 115 $privacy_policy_page_exists = true; 116 } 89 117 } 90 } 91 } 118 } 92 119 93 $title = __( 'Privacy Tools' ); 120 get_current_screen()->add_help_tab( array( 121 'id' => 'privacy', 122 'title' => __( 'Privacy' ), 123 'content' => '<p>' . __( 'This page provides tools with which you can manage your user\'s personal data and site\'s privacy policy.' ) . '</p>', 124 ) ); 94 125 95 get_current_screen()->add_help_tab( array(96 'id' => 'privacy',97 'title' => __( 'Privacy' ),98 'content' => '<p>' . __( 'This page provides tools with which you can manage your user\'s personal data and site\'s privacy policy.' ) . '</p>',99 ) ); 126 get_current_screen()->set_help_sidebar( 127 '<p><strong>' . __( 'For more information:' ) . '</strong></p>' . 128 '<p>' . __( '<a href="#">Documentation on privacy</a>' ) . '</p>' 129 ); 130 } 100 131 101 get_current_screen()->set_help_sidebar(102 '<p><strong>' . __( 'For more information:' ) . '</strong></p>' .103 '<p>' . __( '<a href="#">Documentation on privacy</a>' ) . '</p>'104 );105 106 132 require_once( ABSPATH . 'wp-admin/admin-header.php' ); 107 133 108 134 ?> … … 109 135 <div class="wrap"> 110 136 <h1><?php echo esc_html( $title ); ?></h1> 111 137 <?php settings_errors(); ?> 138 <?php 112 139 113 <h2 class="title"><?php _e( 'Privacy policy page' ); ?></h2> 114 <table class="form-table"> 140 // If we have an email address, bootstrap the exporter 141 if ( ! empty( $doing_personal_data_export_for_email ) ) { 142 if ( $username_or_email_address === $doing_personal_data_export_for_email ) { 143 $heading = sprintf( 144 __( 'Exporting personal data for %s' ), 145 $doing_personal_data_export_for_email 146 ); 147 } else { 148 $heading = sprintf( 149 __( 'Exporting personal data for %1$s (%2$s)' ), 150 $doing_personal_data_export_for_email, 151 $username_or_email_address 152 ); 153 } 154 ?> 155 <p> 156 <?php echo esc_html( $heading ); ?> 157 </p> 158 159 <div id="exporters-container"> 160 <ul id="exporter-list"> 161 </ul> 162 <table class="wp-list-table widefat striped" id="exported-data-table"> 163 <tr> 164 <th><?php _e( 'Name' ); ?></th> 165 <th><?php _e( 'Value' ); ?></th> 166 </tr> 167 </table> 168 </div> 169 115 170 <?php 171 // Build the array of exporters and emit it as an array accessible to javascript along with a nonce 172 $exporters = apply_filters( 'wp_privacy_personal_data_exporters', array() ); 116 173 117 if ( $privacy_policy_page_exists ) { 118 $edit_href = add_query_arg( 119 array( 120 'post' => $privacy_policy_page_id, 121 'action' => 'edit', 122 ), 123 admin_url( 'post.php' ) 124 ); 125 $view_href = get_permalink( $privacy_policy_page_id ); 126 127 ?> 128 <tr> 129 <th colspan="2"> 130 <?php 131 printf( 132 __( '<a href="%1$s">Edit</a> or <a href="%2$s">view</a> your privacy policy.' ), 133 $edit_href, 134 $view_href 135 ); 136 ?> 137 </th> 138 </tr> 139 <?php 174 $exporter_names = array(); 175 foreach ( ( array ) $exporters as $exporter ) { 176 $exporter_names[] = $exporter['exporter_friendly_name']; 140 177 } 141 178 142 179 ?> 143 <tr> 144 <th scope="row"> 180 181 <!-- scripts for the exporter --> 182 183 <script> 184 ( function( $ ) { 185 $( document ).ready( function() { 186 var exportForEmail = <?php echo json_encode( $doing_personal_data_export_for_email ); ?>; 187 var exporterNames = <?php echo json_encode( $exporter_names ); ?>; 188 var successMessage = "<?php echo esc_attr( __( 'Export completed successfully' ) ); ?>"; 189 var failureMessage = "<?php echo esc_attr( __( 'A failure occurred during export' ) ); ?>"; 190 191 function on_exports_done_success() { 192 $( '#exporters-container' ).append( '<p>' + successMessage + '</p>' ); 193 } 194 195 function on_export_failure( textStatus, error ) { 196 $( '#exporters-container' ).append( '<p>' + failureMessage + '</p>' ); 197 $( '#exporters-container' ).append( '<p>' + textStatus + '</p>' ); 198 } 199 200 function do_next_export( exporterIndex, pageIndex ) { 201 $.ajax( { 202 url: ajaxurl, 203 data: { 204 action: 'wp-privacy-export-personal-data', 205 email: exportForEmail, 206 exporter: exporterIndex, 207 page: pageIndex 208 }, 209 method: 'post' 210 } ).done( function( response ) { 211 var responseData = response.data; 212 for ( var dataIndex = 0; dataIndex < responseData.data.length; dataIndex++ ) { 213 $( '#exported-data-table' ).append( '<tr><td>' + responseData.data[ dataIndex ].name + '</td><td>' + responseData.data[ dataIndex ].value + '</td></tr>' ); 214 } 215 if ( ! responseData.done ) { 216 setTimeout( do_next_export( exporterIndex, pageIndex + 1 ) ); 217 } else { 218 if ( exporterIndex < exporterNames.length - 1 ) { 219 setTimeout( do_next_export( exporterIndex + 1, 0 ) ); 220 } else { 221 on_exports_done_success(); 222 } 223 } 224 } ).fail( function( jqxhr, textStatus, error ) { 225 on_export_failure( textStatus, error ); 226 } ); 227 } 228 229 // And now, let's begin 230 do_next_export( 0, 0 ); 231 } ) 232 } ) ( jQuery ); 233 </script> 234 235 <p> 236 <a href="privacy.php"><?php esc_html_e( 'Return to privacy tools' ); ?></a> 237 </p> 238 <?php 239 } else { 240 // No email address to export for? Then just display the privacy tools form table 241 ?> 242 <h2 class="title"><?php _e( 'Privacy policy page' ); ?></h2> 243 <table class="form-table"> 145 244 <?php 146 245 147 246 if ( $privacy_policy_page_exists ) { 148 _e( 'Select another page for your privacy policy' ); 149 } else { 150 _e( 'Select an existing privacy policy page' ); 247 $edit_href = add_query_arg( 248 array( 249 'post' => $privacy_policy_page_id, 250 'action' => 'edit', 251 ), 252 admin_url( 'post.php' ) 253 ); 254 $view_href = get_permalink( $privacy_policy_page_id ); 255 256 ?> 257 <tr> 258 <th colspan="2"> 259 <?php 260 printf( 261 __( '<a href="%1$s">Edit</a> or <a href="%2$s">view</a> your privacy policy.' ), 262 $edit_href, 263 $view_href 264 ); 265 ?> 266 </th> 267 </tr> 268 <?php 151 269 } 152 270 153 271 ?> 154 </th> 155 <td id="front-static-pages"> 156 <form method="post" action=""> 157 <?php wp_nonce_field( 'set-privacy-page' ); ?> 158 <input type="hidden" name="action" value="set-privacy-page" /> 159 <fieldset> 160 <legend class="screen-reader-text"><span><?php _e( 'Select your privacy policy page.' ); ?></span></legend> 161 <label for="page_for_privacy_policy"> 162 <?php wp_dropdown_pages( 163 array( 164 'name' => 'page_for_privacy_policy', 165 'show_option_none' => __( '— Select —' ), 166 'option_none_value' => '0', 167 'selected' => $privacy_policy_page_id, 168 'post_status' => array( 'draft', 'publish' ), 169 ) 170 ); 171 ?> 172 </label> 173 </fieldset> 174 <?php submit_button( __( 'Set Page' ) ); ?> 175 </form> 176 </td> 177 </tr> 178 <?php 272 <tr> 273 <th scope="row"> 274 <?php 179 275 180 if ( ! $privacy_policy_page_exists ) { 276 if ( $privacy_policy_page_exists ) { 277 _e( 'Select another page for your privacy policy' ); 278 } else { 279 _e( 'Select an existing privacy policy page' ); 280 } 281 282 ?> 283 </th> 284 <td id="privacy-policy-page"> 285 <form method="post" action=""> 286 <?php wp_nonce_field( 'set-privacy-page' ); ?> 287 <input type="hidden" name="action" value="set-privacy-page" /> 288 <fieldset> 289 <legend class="screen-reader-text"><span><?php _e( 'Select your privacy policy page.' ); ?></span></legend> 290 <label for="page_for_privacy_policy"> 291 <?php wp_dropdown_pages( 292 array( 293 'name' => 'page_for_privacy_policy', 294 'show_option_none' => __( '— Select —' ), 295 'option_none_value' => '0', 296 'selected' => $privacy_policy_page_id, 297 'post_status' => array( 'draft', 'publish' ), 298 ) 299 ); 300 ?> 301 </label> 302 </fieldset> 303 <?php submit_button( __( 'Set Page' ) ); ?> 304 </form> 305 </td> 306 </tr> 307 <?php 308 309 if ( ! $privacy_policy_page_exists ) { 310 ?> 311 <tr> 312 <th scope="row"><?php _e( 'Create new page for your privacy policy' ); ?></th> 313 <td> 314 <form method="post" action=""> 315 <input type="hidden" name="action" value="create-privacy-page" /> 316 <?php wp_nonce_field( 'create-privacy-page' ); ?> 317 <?php submit_button( __( 'Create Page' ) ); ?> 318 </form> 319 </td> 320 </tr> 321 <?php 322 } 181 323 ?> 324 </table> 325 326 <h2 class="title"><?php _e( 'Personal Data Management' ); ?></h2> 327 <table class="form-table"> 182 328 <tr> 183 <th scope="row"><?php _e( ' Create new page for your privacy policy' ); ?></th>184 <td >329 <th scope="row"><?php _e( 'Export personal data' ); ?></th> 330 <td id="export-personal-data-form-container"> 185 331 <form method="post" action=""> 186 <input type="hidden" name="action" value="create-privacy-page" /> 187 <?php wp_nonce_field( 'create-privacy-page' ); ?> 188 <?php submit_button( __( 'Create Page' ) ); ?> 332 <input type="hidden" name="action" value="export-personal-data" /> 333 <?php wp_nonce_field( 'export-personal-data' ); ?> 334 <fieldset> 335 <legend class="screen-reader-text"><span><?php _e( 'Enter the username or email address of the user whose personal data you wish to export' ); ?></span></legend> 336 <label for="username_or_email_to_export"> 337 <input type="text" class="regular-text" name="username_or_email_to_export" /> 338 </label> 339 <p class="description"><?php _e( 'The username or email address of the user whose personal data you wish to export' ); ?></p> 340 </fieldset> 341 <?php submit_button( __( 'Begin Export' ) ); ?> 189 342 </form> 190 343 </td> 191 344 </tr> 192 <?php 193 } 194 195 ?> 196 </table> 345 </table> 346 <?php 347 } 348 ?> 197 349 </div> 198 350 199 351 <?php -
src/wp-includes/comment.php
3274 3274 3275 3275 return get_comment( $comment_id ); 3276 3276 } 3277 3278 /** 3279 * Registers the personal data exporter for comments 3280 * 3281 * @param array $exporters An array of personal data exporters. 3282 * @return array An array of personal data exporters. 3283 */ 3284 function wp_register_comment_personal_data_exporter( $exporters ) { 3285 $exporters[] = array( 3286 'exporter_friendly_name' => __( 'WordPress Comments' ), 3287 'callback' => 'wp_comments_personal_data_exporter' 3288 ); 3289 3290 return $exporters; 3291 } 3292 3293 /** 3294 * Finds and exports data which could be used to identify a person from comments assocated with an email address. 3295 * 3296 * @param string $email The comment author email address. 3297 * @param int $page Comment page. 3298 * @return array An array of personal data in name value pairs 3299 */ 3300 function wp_comments_personal_data_exporter( $email_address, $page ) { 3301 3302 $personal_data = array(); 3303 $email_address = trim( strtolower( $email_address ) ); 3304 3305 // TODO - actually use the page parameter to avoid fetching all the comments at once 3306 // that will be a no-no on sites with lots of comments 3307 3308 // TODO - pass the email address to get_comments if possible to be most performant 3309 3310 $comments = get_comments( 3311 array( 3312 'order_by' => 'comment_ID', 3313 'order' => 'ASC' 3314 ) 3315 ); 3316 3317 $comment_personal_data_props = array( 3318 'comment_author' => __( 'Comment Author' ), 3319 'comment_author_email' => __( 'Comment Author Email' ), 3320 'comment_author_url' => __( 'Comment Author URL' ), 3321 'comment_author_IP' => __( 'Comment Author IP' ), 3322 'comment_agent' => __( 'Comment Agent' ) 3323 ); 3324 3325 foreach ( (array) $comments as $comment ) { 3326 $comment_author_email = trim( strtolower( $comment->comment_author_email ) ); 3327 if ( $comment_author_email === $email_address ) { 3328 foreach ( (array) $comment_personal_data_props as $key => $description ) { 3329 $value = $comment->$key; 3330 if ( ! empty( $value ) ) { 3331 $name = sprintf( 3332 __( 'Comment %d : %s' ), 3333 $comment->comment_ID, 3334 $description 3335 ); 3336 $personal_data[] = array( 3337 'name' => $name, 3338 'value' => $value 3339 ); 3340 } 3341 } 3342 } 3343 } 3344 3345 return array( 3346 'data' => $personal_data, 3347 'done' => true, 3348 ); 3349 } -
src/wp-includes/default-filters.php
328 328 add_action( 'do_pings', 'do_all_pings', 10, 1 ); 329 329 add_action( 'do_robots', 'do_robots' ); 330 330 add_action( 'set_comment_cookies', 'wp_set_comment_cookies', 10, 3 ); 331 add_filter( 'wp_privacy_personal_data_exporters', 'wp_register_comment_personal_data_exporter', 10 ); 331 332 add_action( 'sanitize_comment_cookies', 'sanitize_comment_cookies' ); 332 333 add_action( 'admin_print_scripts', 'print_emoji_detection_script' ); 333 334 add_action( 'admin_print_scripts', 'print_head_scripts', 20 );