Edit File by line
/home/barbar84/public_h.../wp-admin/includes
File: privacy-tools.php
<?php
[0] Fix | Delete
/**
[1] Fix | Delete
* WordPress Administration Privacy Tools API.
[2] Fix | Delete
*
[3] Fix | Delete
* @package WordPress
[4] Fix | Delete
* @subpackage Administration
[5] Fix | Delete
*/
[6] Fix | Delete
[7] Fix | Delete
/**
[8] Fix | Delete
* Resend an existing request and return the result.
[9] Fix | Delete
*
[10] Fix | Delete
* @since 4.9.6
[11] Fix | Delete
* @access private
[12] Fix | Delete
*
[13] Fix | Delete
* @param int $request_id Request ID.
[14] Fix | Delete
* @return true|WP_Error Returns true if sending the email was successful, or a WP_Error object.
[15] Fix | Delete
*/
[16] Fix | Delete
function _wp_privacy_resend_request( $request_id ) {
[17] Fix | Delete
$request_id = absint( $request_id );
[18] Fix | Delete
$request = get_post( $request_id );
[19] Fix | Delete
[20] Fix | Delete
if ( ! $request || 'user_request' !== $request->post_type ) {
[21] Fix | Delete
return new WP_Error( 'privacy_request_error', __( 'Invalid personal data request.' ) );
[22] Fix | Delete
}
[23] Fix | Delete
[24] Fix | Delete
$result = wp_send_user_request( $request_id );
[25] Fix | Delete
[26] Fix | Delete
if ( is_wp_error( $result ) ) {
[27] Fix | Delete
return $result;
[28] Fix | Delete
} elseif ( ! $result ) {
[29] Fix | Delete
return new WP_Error( 'privacy_request_error', __( 'Unable to initiate confirmation for personal data request.' ) );
[30] Fix | Delete
}
[31] Fix | Delete
[32] Fix | Delete
return true;
[33] Fix | Delete
}
[34] Fix | Delete
[35] Fix | Delete
/**
[36] Fix | Delete
* Marks a request as completed by the admin and logs the current timestamp.
[37] Fix | Delete
*
[38] Fix | Delete
* @since 4.9.6
[39] Fix | Delete
* @access private
[40] Fix | Delete
*
[41] Fix | Delete
* @param int $request_id Request ID.
[42] Fix | Delete
* @return int|WP_Error Request ID on success, or a WP_Error on failure.
[43] Fix | Delete
*/
[44] Fix | Delete
function _wp_privacy_completed_request( $request_id ) {
[45] Fix | Delete
// Get the request.
[46] Fix | Delete
$request_id = absint( $request_id );
[47] Fix | Delete
$request = wp_get_user_request( $request_id );
[48] Fix | Delete
[49] Fix | Delete
if ( ! $request ) {
[50] Fix | Delete
return new WP_Error( 'privacy_request_error', __( 'Invalid personal data request.' ) );
[51] Fix | Delete
}
[52] Fix | Delete
[53] Fix | Delete
update_post_meta( $request_id, '_wp_user_request_completed_timestamp', time() );
[54] Fix | Delete
[55] Fix | Delete
$result = wp_update_post(
[56] Fix | Delete
array(
[57] Fix | Delete
'ID' => $request_id,
[58] Fix | Delete
'post_status' => 'request-completed',
[59] Fix | Delete
)
[60] Fix | Delete
);
[61] Fix | Delete
[62] Fix | Delete
return $result;
[63] Fix | Delete
}
[64] Fix | Delete
[65] Fix | Delete
/**
[66] Fix | Delete
* Handle list table actions.
[67] Fix | Delete
*
[68] Fix | Delete
* @since 4.9.6
[69] Fix | Delete
* @access private
[70] Fix | Delete
*/
[71] Fix | Delete
function _wp_personal_data_handle_actions() {
[72] Fix | Delete
if ( isset( $_POST['privacy_action_email_retry'] ) ) {
[73] Fix | Delete
check_admin_referer( 'bulk-privacy_requests' );
[74] Fix | Delete
[75] Fix | Delete
$request_id = absint( current( array_keys( (array) wp_unslash( $_POST['privacy_action_email_retry'] ) ) ) );
[76] Fix | Delete
$result = _wp_privacy_resend_request( $request_id );
[77] Fix | Delete
[78] Fix | Delete
if ( is_wp_error( $result ) ) {
[79] Fix | Delete
add_settings_error(
[80] Fix | Delete
'privacy_action_email_retry',
[81] Fix | Delete
'privacy_action_email_retry',
[82] Fix | Delete
$result->get_error_message(),
[83] Fix | Delete
'error'
[84] Fix | Delete
);
[85] Fix | Delete
} else {
[86] Fix | Delete
add_settings_error(
[87] Fix | Delete
'privacy_action_email_retry',
[88] Fix | Delete
'privacy_action_email_retry',
[89] Fix | Delete
__( 'Confirmation request sent again successfully.' ),
[90] Fix | Delete
'success'
[91] Fix | Delete
);
[92] Fix | Delete
}
[93] Fix | Delete
} elseif ( isset( $_POST['action'] ) ) {
[94] Fix | Delete
$action = ! empty( $_POST['action'] ) ? sanitize_key( wp_unslash( $_POST['action'] ) ) : '';
[95] Fix | Delete
[96] Fix | Delete
switch ( $action ) {
[97] Fix | Delete
case 'add_export_personal_data_request':
[98] Fix | Delete
case 'add_remove_personal_data_request':
[99] Fix | Delete
check_admin_referer( 'personal-data-request' );
[100] Fix | Delete
[101] Fix | Delete
if ( ! isset( $_POST['type_of_action'], $_POST['username_or_email_for_privacy_request'] ) ) {
[102] Fix | Delete
add_settings_error(
[103] Fix | Delete
'action_type',
[104] Fix | Delete
'action_type',
[105] Fix | Delete
__( 'Invalid personal data action.' ),
[106] Fix | Delete
'error'
[107] Fix | Delete
);
[108] Fix | Delete
}
[109] Fix | Delete
$action_type = sanitize_text_field( wp_unslash( $_POST['type_of_action'] ) );
[110] Fix | Delete
$username_or_email_address = sanitize_text_field( wp_unslash( $_POST['username_or_email_for_privacy_request'] ) );
[111] Fix | Delete
$email_address = '';
[112] Fix | Delete
$status = 'pending';
[113] Fix | Delete
[114] Fix | Delete
if ( ! isset( $_POST['send_confirmation_email'] ) ) {
[115] Fix | Delete
$status = 'confirmed';
[116] Fix | Delete
}
[117] Fix | Delete
[118] Fix | Delete
if ( ! in_array( $action_type, _wp_privacy_action_request_types(), true ) ) {
[119] Fix | Delete
add_settings_error(
[120] Fix | Delete
'action_type',
[121] Fix | Delete
'action_type',
[122] Fix | Delete
__( 'Invalid personal data action.' ),
[123] Fix | Delete
'error'
[124] Fix | Delete
);
[125] Fix | Delete
}
[126] Fix | Delete
[127] Fix | Delete
if ( ! is_email( $username_or_email_address ) ) {
[128] Fix | Delete
$user = get_user_by( 'login', $username_or_email_address );
[129] Fix | Delete
if ( ! $user instanceof WP_User ) {
[130] Fix | Delete
add_settings_error(
[131] Fix | Delete
'username_or_email_for_privacy_request',
[132] Fix | Delete
'username_or_email_for_privacy_request',
[133] Fix | Delete
__( 'Unable to add this request. A valid email address or username must be supplied.' ),
[134] Fix | Delete
'error'
[135] Fix | Delete
);
[136] Fix | Delete
} else {
[137] Fix | Delete
$email_address = $user->user_email;
[138] Fix | Delete
}
[139] Fix | Delete
} else {
[140] Fix | Delete
$email_address = $username_or_email_address;
[141] Fix | Delete
}
[142] Fix | Delete
[143] Fix | Delete
if ( empty( $email_address ) ) {
[144] Fix | Delete
break;
[145] Fix | Delete
}
[146] Fix | Delete
[147] Fix | Delete
$request_id = wp_create_user_request( $email_address, $action_type, array(), $status );
[148] Fix | Delete
$message = '';
[149] Fix | Delete
[150] Fix | Delete
if ( is_wp_error( $request_id ) ) {
[151] Fix | Delete
$message = $request_id->get_error_message();
[152] Fix | Delete
} elseif ( ! $request_id ) {
[153] Fix | Delete
$message = __( 'Unable to initiate confirmation request.' );
[154] Fix | Delete
}
[155] Fix | Delete
[156] Fix | Delete
if ( $message ) {
[157] Fix | Delete
add_settings_error(
[158] Fix | Delete
'username_or_email_for_privacy_request',
[159] Fix | Delete
'username_or_email_for_privacy_request',
[160] Fix | Delete
$message,
[161] Fix | Delete
'error'
[162] Fix | Delete
);
[163] Fix | Delete
break;
[164] Fix | Delete
}
[165] Fix | Delete
[166] Fix | Delete
if ( 'pending' === $status ) {
[167] Fix | Delete
wp_send_user_request( $request_id );
[168] Fix | Delete
[169] Fix | Delete
$message = __( 'Confirmation request initiated successfully.' );
[170] Fix | Delete
} elseif ( 'confirmed' === $status ) {
[171] Fix | Delete
$message = __( 'Request added successfully.' );
[172] Fix | Delete
}
[173] Fix | Delete
[174] Fix | Delete
if ( $message ) {
[175] Fix | Delete
add_settings_error(
[176] Fix | Delete
'username_or_email_for_privacy_request',
[177] Fix | Delete
'username_or_email_for_privacy_request',
[178] Fix | Delete
$message,
[179] Fix | Delete
'success'
[180] Fix | Delete
);
[181] Fix | Delete
break;
[182] Fix | Delete
}
[183] Fix | Delete
}
[184] Fix | Delete
}
[185] Fix | Delete
}
[186] Fix | Delete
[187] Fix | Delete
/**
[188] Fix | Delete
* Cleans up failed and expired requests before displaying the list table.
[189] Fix | Delete
*
[190] Fix | Delete
* @since 4.9.6
[191] Fix | Delete
* @access private
[192] Fix | Delete
*/
[193] Fix | Delete
function _wp_personal_data_cleanup_requests() {
[194] Fix | Delete
/** This filter is documented in wp-includes/user.php */
[195] Fix | Delete
$expires = (int) apply_filters( 'user_request_key_expiration', DAY_IN_SECONDS );
[196] Fix | Delete
[197] Fix | Delete
$requests_query = new WP_Query(
[198] Fix | Delete
array(
[199] Fix | Delete
'post_type' => 'user_request',
[200] Fix | Delete
'posts_per_page' => -1,
[201] Fix | Delete
'post_status' => 'request-pending',
[202] Fix | Delete
'fields' => 'ids',
[203] Fix | Delete
'date_query' => array(
[204] Fix | Delete
array(
[205] Fix | Delete
'column' => 'post_modified_gmt',
[206] Fix | Delete
'before' => $expires . ' seconds ago',
[207] Fix | Delete
),
[208] Fix | Delete
),
[209] Fix | Delete
)
[210] Fix | Delete
);
[211] Fix | Delete
[212] Fix | Delete
$request_ids = $requests_query->posts;
[213] Fix | Delete
[214] Fix | Delete
foreach ( $request_ids as $request_id ) {
[215] Fix | Delete
wp_update_post(
[216] Fix | Delete
array(
[217] Fix | Delete
'ID' => $request_id,
[218] Fix | Delete
'post_status' => 'request-failed',
[219] Fix | Delete
'post_password' => '',
[220] Fix | Delete
)
[221] Fix | Delete
);
[222] Fix | Delete
}
[223] Fix | Delete
}
[224] Fix | Delete
[225] Fix | Delete
/**
[226] Fix | Delete
* Generate a single group for the personal data export report.
[227] Fix | Delete
*
[228] Fix | Delete
* @since 4.9.6
[229] Fix | Delete
* @since 5.4.0 Added the `$group_id` and `$groups_count` parameters.
[230] Fix | Delete
*
[231] Fix | Delete
* @param array $group_data {
[232] Fix | Delete
* The group data to render.
[233] Fix | Delete
*
[234] Fix | Delete
* @type string $group_label The user-facing heading for the group, e.g. 'Comments'.
[235] Fix | Delete
* @type array $items {
[236] Fix | Delete
* An array of group items.
[237] Fix | Delete
*
[238] Fix | Delete
* @type array $group_item_data {
[239] Fix | Delete
* An array of name-value pairs for the item.
[240] Fix | Delete
*
[241] Fix | Delete
* @type string $name The user-facing name of an item name-value pair, e.g. 'IP Address'.
[242] Fix | Delete
* @type string $value The user-facing value of an item data pair, e.g. '50.60.70.0'.
[243] Fix | Delete
* }
[244] Fix | Delete
* }
[245] Fix | Delete
* }
[246] Fix | Delete
* @param string $group_id The group identifier.
[247] Fix | Delete
* @param int $groups_count The number of all groups
[248] Fix | Delete
* @return string The HTML for this group and its items.
[249] Fix | Delete
*/
[250] Fix | Delete
function wp_privacy_generate_personal_data_export_group_html( $group_data, $group_id = '', $groups_count = 1 ) {
[251] Fix | Delete
$group_id_attr = sanitize_title_with_dashes( $group_data['group_label'] . '-' . $group_id );
[252] Fix | Delete
[253] Fix | Delete
$group_html = '<h2 id="' . esc_attr( $group_id_attr ) . '">';
[254] Fix | Delete
$group_html .= esc_html( $group_data['group_label'] );
[255] Fix | Delete
[256] Fix | Delete
$items_count = count( (array) $group_data['items'] );
[257] Fix | Delete
if ( $items_count > 1 ) {
[258] Fix | Delete
$group_html .= sprintf( ' <span class="count">(%d)</span>', $items_count );
[259] Fix | Delete
}
[260] Fix | Delete
[261] Fix | Delete
$group_html .= '</h2>';
[262] Fix | Delete
[263] Fix | Delete
if ( ! empty( $group_data['group_description'] ) ) {
[264] Fix | Delete
$group_html .= '<p>' . esc_html( $group_data['group_description'] ) . '</p>';
[265] Fix | Delete
}
[266] Fix | Delete
[267] Fix | Delete
$group_html .= '<div>';
[268] Fix | Delete
[269] Fix | Delete
foreach ( (array) $group_data['items'] as $group_item_id => $group_item_data ) {
[270] Fix | Delete
$group_html .= '<table>';
[271] Fix | Delete
$group_html .= '<tbody>';
[272] Fix | Delete
[273] Fix | Delete
foreach ( (array) $group_item_data as $group_item_datum ) {
[274] Fix | Delete
$value = $group_item_datum['value'];
[275] Fix | Delete
// If it looks like a link, make it a link.
[276] Fix | Delete
if ( false === strpos( $value, ' ' ) && ( 0 === strpos( $value, 'http://' ) || 0 === strpos( $value, 'https://' ) ) ) {
[277] Fix | Delete
$value = '<a href="' . esc_url( $value ) . '">' . esc_html( $value ) . '</a>';
[278] Fix | Delete
}
[279] Fix | Delete
[280] Fix | Delete
$group_html .= '<tr>';
[281] Fix | Delete
$group_html .= '<th>' . esc_html( $group_item_datum['name'] ) . '</th>';
[282] Fix | Delete
$group_html .= '<td>' . wp_kses( $value, 'personal_data_export' ) . '</td>';
[283] Fix | Delete
$group_html .= '</tr>';
[284] Fix | Delete
}
[285] Fix | Delete
[286] Fix | Delete
$group_html .= '</tbody>';
[287] Fix | Delete
$group_html .= '</table>';
[288] Fix | Delete
}
[289] Fix | Delete
[290] Fix | Delete
if ( $groups_count > 1 ) {
[291] Fix | Delete
$group_html .= '<div class="return-to-top">';
[292] Fix | Delete
$group_html .= '<a href="#top"><span aria-hidden="true">&uarr; </span> ' . esc_html__( 'Go to top' ) . '</a>';
[293] Fix | Delete
$group_html .= '</div>';
[294] Fix | Delete
}
[295] Fix | Delete
[296] Fix | Delete
$group_html .= '</div>';
[297] Fix | Delete
[298] Fix | Delete
return $group_html;
[299] Fix | Delete
}
[300] Fix | Delete
[301] Fix | Delete
/**
[302] Fix | Delete
* Generate the personal data export file.
[303] Fix | Delete
*
[304] Fix | Delete
* @since 4.9.6
[305] Fix | Delete
*
[306] Fix | Delete
* @param int $request_id The export request ID.
[307] Fix | Delete
*/
[308] Fix | Delete
function wp_privacy_generate_personal_data_export_file( $request_id ) {
[309] Fix | Delete
if ( ! class_exists( 'ZipArchive' ) ) {
[310] Fix | Delete
wp_send_json_error( __( 'Unable to generate personal data export file. ZipArchive not available.' ) );
[311] Fix | Delete
}
[312] Fix | Delete
[313] Fix | Delete
// Get the request.
[314] Fix | Delete
$request = wp_get_user_request( $request_id );
[315] Fix | Delete
[316] Fix | Delete
if ( ! $request || 'export_personal_data' !== $request->action_name ) {
[317] Fix | Delete
wp_send_json_error( __( 'Invalid request ID when generating personal data export file.' ) );
[318] Fix | Delete
}
[319] Fix | Delete
[320] Fix | Delete
$email_address = $request->email;
[321] Fix | Delete
[322] Fix | Delete
if ( ! is_email( $email_address ) ) {
[323] Fix | Delete
wp_send_json_error( __( 'Invalid email address when generating personal data export file.' ) );
[324] Fix | Delete
}
[325] Fix | Delete
[326] Fix | Delete
// Create the exports folder if needed.
[327] Fix | Delete
$exports_dir = wp_privacy_exports_dir();
[328] Fix | Delete
$exports_url = wp_privacy_exports_url();
[329] Fix | Delete
[330] Fix | Delete
if ( ! wp_mkdir_p( $exports_dir ) ) {
[331] Fix | Delete
wp_send_json_error( __( 'Unable to create personal data export folder.' ) );
[332] Fix | Delete
}
[333] Fix | Delete
[334] Fix | Delete
// Protect export folder from browsing.
[335] Fix | Delete
$index_pathname = $exports_dir . 'index.php';
[336] Fix | Delete
if ( ! file_exists( $index_pathname ) ) {
[337] Fix | Delete
$file = fopen( $index_pathname, 'w' );
[338] Fix | Delete
if ( false === $file ) {
[339] Fix | Delete
wp_send_json_error( __( 'Unable to protect personal data export folder from browsing.' ) );
[340] Fix | Delete
}
[341] Fix | Delete
fwrite( $file, "<?php\n// Silence is golden.\n" );
[342] Fix | Delete
fclose( $file );
[343] Fix | Delete
}
[344] Fix | Delete
[345] Fix | Delete
$obscura = wp_generate_password( 32, false, false );
[346] Fix | Delete
$file_basename = 'wp-personal-data-file-' . $obscura;
[347] Fix | Delete
$html_report_filename = wp_unique_filename( $exports_dir, $file_basename . '.html' );
[348] Fix | Delete
$html_report_pathname = wp_normalize_path( $exports_dir . $html_report_filename );
[349] Fix | Delete
$json_report_filename = $file_basename . '.json';
[350] Fix | Delete
$json_report_pathname = wp_normalize_path( $exports_dir . $json_report_filename );
[351] Fix | Delete
[352] Fix | Delete
/*
[353] Fix | Delete
* Gather general data needed.
[354] Fix | Delete
*/
[355] Fix | Delete
[356] Fix | Delete
// Title.
[357] Fix | Delete
$title = sprintf(
[358] Fix | Delete
/* translators: %s: User's email address. */
[359] Fix | Delete
__( 'Personal Data Export for %s' ),
[360] Fix | Delete
$email_address
[361] Fix | Delete
);
[362] Fix | Delete
[363] Fix | Delete
// And now, all the Groups.
[364] Fix | Delete
$groups = get_post_meta( $request_id, '_export_data_grouped', true );
[365] Fix | Delete
[366] Fix | Delete
// First, build an "About" group on the fly for this report.
[367] Fix | Delete
$about_group = array(
[368] Fix | Delete
/* translators: Header for the About section in a personal data export. */
[369] Fix | Delete
'group_label' => _x( 'About', 'personal data group label' ),
[370] Fix | Delete
/* translators: Description for the About section in a personal data export. */
[371] Fix | Delete
'group_description' => _x( 'Overview of export report.', 'personal data group description' ),
[372] Fix | Delete
'items' => array(
[373] Fix | Delete
'about-1' => array(
[374] Fix | Delete
array(
[375] Fix | Delete
'name' => _x( 'Report generated for', 'email address' ),
[376] Fix | Delete
'value' => $email_address,
[377] Fix | Delete
),
[378] Fix | Delete
array(
[379] Fix | Delete
'name' => _x( 'For site', 'website name' ),
[380] Fix | Delete
'value' => get_bloginfo( 'name' ),
[381] Fix | Delete
),
[382] Fix | Delete
array(
[383] Fix | Delete
'name' => _x( 'At URL', 'website URL' ),
[384] Fix | Delete
'value' => get_bloginfo( 'url' ),
[385] Fix | Delete
),
[386] Fix | Delete
array(
[387] Fix | Delete
'name' => _x( 'On', 'date/time' ),
[388] Fix | Delete
'value' => current_time( 'mysql' ),
[389] Fix | Delete
),
[390] Fix | Delete
),
[391] Fix | Delete
),
[392] Fix | Delete
);
[393] Fix | Delete
[394] Fix | Delete
// Merge in the special about group.
[395] Fix | Delete
$groups = array_merge( array( 'about' => $about_group ), $groups );
[396] Fix | Delete
[397] Fix | Delete
$groups_count = count( $groups );
[398] Fix | Delete
[399] Fix | Delete
// Convert the groups to JSON format.
[400] Fix | Delete
$groups_json = wp_json_encode( $groups );
[401] Fix | Delete
[402] Fix | Delete
/*
[403] Fix | Delete
* Handle the JSON export.
[404] Fix | Delete
*/
[405] Fix | Delete
$file = fopen( $json_report_pathname, 'w' );
[406] Fix | Delete
[407] Fix | Delete
if ( false === $file ) {
[408] Fix | Delete
wp_send_json_error( __( 'Unable to open personal data export file (JSON report) for writing.' ) );
[409] Fix | Delete
}
[410] Fix | Delete
[411] Fix | Delete
fwrite( $file, '{' );
[412] Fix | Delete
fwrite( $file, '"' . $title . '":' );
[413] Fix | Delete
fwrite( $file, $groups_json );
[414] Fix | Delete
fwrite( $file, '}' );
[415] Fix | Delete
fclose( $file );
[416] Fix | Delete
[417] Fix | Delete
/*
[418] Fix | Delete
* Handle the HTML export.
[419] Fix | Delete
*/
[420] Fix | Delete
$file = fopen( $html_report_pathname, 'w' );
[421] Fix | Delete
[422] Fix | Delete
if ( false === $file ) {
[423] Fix | Delete
wp_send_json_error( __( 'Unable to open personal data export (HTML report) for writing.' ) );
[424] Fix | Delete
}
[425] Fix | Delete
[426] Fix | Delete
fwrite( $file, "<!DOCTYPE html>\n" );
[427] Fix | Delete
fwrite( $file, "<html>\n" );
[428] Fix | Delete
fwrite( $file, "<head>\n" );
[429] Fix | Delete
fwrite( $file, "<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />\n" );
[430] Fix | Delete
fwrite( $file, "<style type='text/css'>" );
[431] Fix | Delete
fwrite( $file, 'body { color: black; font-family: Arial, sans-serif; font-size: 11pt; margin: 15px auto; width: 860px; }' );
[432] Fix | Delete
fwrite( $file, 'table { background: #f0f0f0; border: 1px solid #ddd; margin-bottom: 20px; width: 100%; }' );
[433] Fix | Delete
fwrite( $file, 'th { padding: 5px; text-align: left; width: 20%; }' );
[434] Fix | Delete
fwrite( $file, 'td { padding: 5px; }' );
[435] Fix | Delete
fwrite( $file, 'tr:nth-child(odd) { background-color: #fafafa; }' );
[436] Fix | Delete
fwrite( $file, '.return-to-top { text-align: right; }' );
[437] Fix | Delete
fwrite( $file, '</style>' );
[438] Fix | Delete
fwrite( $file, '<title>' );
[439] Fix | Delete
fwrite( $file, esc_html( $title ) );
[440] Fix | Delete
fwrite( $file, '</title>' );
[441] Fix | Delete
fwrite( $file, "</head>\n" );
[442] Fix | Delete
fwrite( $file, "<body>\n" );
[443] Fix | Delete
fwrite( $file, '<h1 id="top">' . esc_html__( 'Personal Data Export' ) . '</h1>' );
[444] Fix | Delete
[445] Fix | Delete
// Create TOC.
[446] Fix | Delete
if ( $groups_count > 1 ) {
[447] Fix | Delete
fwrite( $file, '<div id="table_of_contents">' );
[448] Fix | Delete
fwrite( $file, '<h2>' . esc_html__( 'Table of Contents' ) . '</h2>' );
[449] Fix | Delete
fwrite( $file, '<ul>' );
[450] Fix | Delete
foreach ( (array) $groups as $group_id => $group_data ) {
[451] Fix | Delete
$group_label = esc_html( $group_data['group_label'] );
[452] Fix | Delete
$group_id_attr = sanitize_title_with_dashes( $group_data['group_label'] . '-' . $group_id );
[453] Fix | Delete
$group_items_count = count( (array) $group_data['items'] );
[454] Fix | Delete
if ( $group_items_count > 1 ) {
[455] Fix | Delete
$group_label .= sprintf( ' <span class="count">(%d)</span>', $group_items_count );
[456] Fix | Delete
}
[457] Fix | Delete
fwrite( $file, '<li>' );
[458] Fix | Delete
fwrite( $file, '<a href="#' . esc_attr( $group_id_attr ) . '">' . $group_label . '</a>' );
[459] Fix | Delete
fwrite( $file, '</li>' );
[460] Fix | Delete
}
[461] Fix | Delete
fwrite( $file, '</ul>' );
[462] Fix | Delete
fwrite( $file, '</div>' );
[463] Fix | Delete
}
[464] Fix | Delete
[465] Fix | Delete
// Now, iterate over every group in $groups and have the formatter render it in HTML.
[466] Fix | Delete
foreach ( (array) $groups as $group_id => $group_data ) {
[467] Fix | Delete
fwrite( $file, wp_privacy_generate_personal_data_export_group_html( $group_data, $group_id, $groups_count ) );
[468] Fix | Delete
}
[469] Fix | Delete
[470] Fix | Delete
fwrite( $file, "</body>\n" );
[471] Fix | Delete
fwrite( $file, "</html>\n" );
[472] Fix | Delete
fclose( $file );
[473] Fix | Delete
[474] Fix | Delete
/*
[475] Fix | Delete
* Now, generate the ZIP.
[476] Fix | Delete
*
[477] Fix | Delete
* If an archive has already been generated, then remove it and reuse the filename,
[478] Fix | Delete
* to avoid breaking any URLs that may have been previously sent via email.
[479] Fix | Delete
*/
[480] Fix | Delete
$error = false;
[481] Fix | Delete
[482] Fix | Delete
// This meta value is used from version 5.5.
[483] Fix | Delete
$archive_filename = get_post_meta( $request_id, '_export_file_name', true );
[484] Fix | Delete
[485] Fix | Delete
// This one stored an absolute path and is used for backward compatibility.
[486] Fix | Delete
$archive_pathname = get_post_meta( $request_id, '_export_file_path', true );
[487] Fix | Delete
[488] Fix | Delete
// If a filename meta exists, use it.
[489] Fix | Delete
if ( ! empty( $archive_filename ) ) {
[490] Fix | Delete
$archive_pathname = $exports_dir . $archive_filename;
[491] Fix | Delete
} elseif ( ! empty( $archive_pathname ) ) {
[492] Fix | Delete
// If a full path meta exists, use it and create the new meta value.
[493] Fix | Delete
$archive_filename = basename( $archive_pathname );
[494] Fix | Delete
[495] Fix | Delete
update_post_meta( $request_id, '_export_file_name', $archive_filename );
[496] Fix | Delete
[497] Fix | Delete
// Remove the back-compat meta values.
[498] Fix | Delete
delete_post_meta( $request_id, '_export_file_url' );
[499] Fix | Delete
12
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function