Changeset 43092
- Timestamp:
- 05/02/2018 02:15:05 AM (7 years ago)
- Location:
- branches/4.9
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/4.9
- Property svn:mergeinfo changed
/trunk merged: 43012,43089
- Property svn:mergeinfo changed
-
branches/4.9/src/wp-admin/includes/admin-filters.php
r43083 r43092 132 132 add_action( 'upgrader_process_complete', 'wp_update_plugins', 10, 0 ); 133 133 add_action( 'upgrader_process_complete', 'wp_update_themes', 10, 0 ); 134 135 // Privacy hooks 136 add_filter( 'wp_privacy_personal_data_export_page', 'wp_privacy_process_personal_data_export_page', 10, 6 ); 137 add_action( 'wp_privacy_personal_data_export_file', 'wp_privacy_generate_personal_data_export_file', 10 ); -
branches/4.9/src/wp-admin/includes/ajax-actions.php
r43084 r43092 4019 4019 } 4020 4020 4021 /** 4022 * Ajax handler for exporting a user's personal data. 4023 * 4024 * @since 4.9.6 4025 */ 4021 4026 function wp_ajax_wp_privacy_export_personal_data() { 4022 check_ajax_referer( 'wp-privacy-export-personal-data', 'security' ); 4027 $request_id = (int) $_POST['id']; 4028 4029 if ( empty( $request_id ) ) { 4030 wp_send_json_error( __( 'Error: Invalid request ID.' ) ); 4031 } 4023 4032 4024 4033 if ( ! current_user_can( 'manage_options' ) ) { … … 4026 4035 } 4027 4036 4028 $email_address = sanitize_text_field( $_POST['email'] ); 4037 check_ajax_referer( 'wp-privacy-export-personal-data-' . $request_id, 'security' ); 4038 4039 // Get the request data. 4040 $request = wp_get_user_request_data( $request_id ); 4041 4042 if ( ! $request || 'export_personal_data' !== $request->action_name ) { 4043 wp_send_json_error( __( 'Error: Invalid request type.' ) ); 4044 } 4045 4046 $email_address = $request->email; 4047 if ( ! is_email( $email_address ) ) { 4048 wp_send_json_error( __( 'Error: A valid email address must be given.' ) ); 4049 } 4050 4029 4051 $exporter_index = (int) $_POST['exporter']; 4030 4052 $page = (int) $_POST['page']; 4053 $send_as_email = isset( $_POST['sendAsEmail'] ) ? ( "true" === $_POST['sendAsEmail'] ) : false; 4031 4054 4032 4055 /** … … 4040 4063 * callback string Callable exporter that accepts an email address and 4041 4064 * a page and returns an array of name => value 4042 * pairs of personal data 4043 * exporter_friendly_name string Translated user facing friendly name for the exporter 4065 * pairs of personal data. 4066 * exporter_friendly_name string Translated user facing friendly name for the exporter. 4044 4067 * ] 4045 4068 * } … … 4067 4090 } 4068 4091 4069 // Surprisingly, email addresses can contain mutli-byte characters now4070 $email_address = trim( mb_strtolower( $email_address ) );4071 4072 if ( ! is_email( $email_address ) ) {4073 wp_send_json_error( 'A valid email address must be given.' );4074 }4075 4076 4092 $exporter = $exporters[ $index ]; 4093 4077 4094 if ( ! is_array( $exporter ) ) { 4078 4095 wp_send_json_error( "Expected an array describing the exporter at index {$exporter_index}." ); 4079 4096 } 4080 if ( ! array_key_exists( 'callback', $exporter ) ) {4081 wp_send_json_error( "Exporter array at index {$exporter_index} does not include a callback." );4082 }4083 if ( ! is_callable( $exporter['callback'] ) ) {4084 wp_send_json_error( "Exporter callback at index {$exporter_index} is not a valid callback." );4085 }4086 4097 if ( ! array_key_exists( 'exporter_friendly_name', $exporter ) ) { 4087 4098 wp_send_json_error( "Exporter array at index {$exporter_index} does not include a friendly name." ); 4099 } 4100 if ( ! array_key_exists( 'callback', $exporter ) ) { 4101 wp_send_json_error( "Exporter does not include a callback: {$exporter['exporter_friendly_name']}." ); 4102 } 4103 if ( ! is_callable( $exporter['callback'] ) ) { 4104 wp_send_json_error( "Exporter callback is not a valid callback: {$exporter['exporter_friendly_name']}." ); 4088 4105 } 4089 4106 … … 4109 4126 } 4110 4127 } else { 4111 // No exporters, so we're done 4128 // No exporters, so we're done. 4112 4129 $response = array( 4113 4130 'data' => array(), … … 4127 4144 * @param string $email_address The email address associated with this personal data. 4128 4145 * @param int $page The zero-based page for this response. 4146 * @param int $request_id The privacy request post ID associated with this request. 4147 * @param bool $send_as_email Whether the final results of the export should be emailed to the user. 4129 4148 */ 4130 $response = apply_filters( 'wp_privacy_personal_data_export_page', $response, $exporter_index, $email_address, $page ); 4149 $response = apply_filters( 'wp_privacy_personal_data_export_page', $response, $exporter_index, $email_address, $page, $request_id, $send_as_email ); 4150 4131 4151 if ( is_wp_error( $response ) ) { 4132 4152 wp_send_json_error( $response ); … … 4154 4174 check_ajax_referer( 'wp-privacy-erase-personal-data-' . $request_id, 'security' ); 4155 4175 4156 // Find the request CPT4176 // Get the request data. 4157 4177 $request = wp_get_user_request_data( $request_id ); 4158 4178 -
branches/4.9/src/wp-admin/includes/file.php
r42811 r43092 1798 1798 <?php 1799 1799 } 1800 1801 /** 1802 * Generate a single group for the personal data export report. 1803 * 1804 * @since 4.9.6 1805 * 1806 * @param array $group_data { 1807 * The group data to render. 1808 * 1809 * @type string $group_label The user-facing heading for the group, e.g. 'Comments'. 1810 * @type array $items { 1811 * An array of group items. 1812 * 1813 * @type array $group_item_data { 1814 * An array of name-value pairs for the item. 1815 * 1816 * @type string $name The user-facing name of an item name-value pair, e.g. 'IP Address'. 1817 * @type string $value The user-facing value of an item data pair, e.g. '50.60.70.0'. 1818 * } 1819 * } 1820 * } 1821 * @return string The HTML for this group and its items. 1822 */ 1823 function wp_privacy_generate_personal_data_export_group_html( $group_data ) { 1824 $allowed_tags = array( 1825 'a' => array( 1826 'href' => array(), 1827 'target' => array() 1828 ), 1829 'br' => array() 1830 ); 1831 $allowed_protocols = array( 'http', 'https' ); 1832 $group_html = ''; 1833 1834 $group_html .= '<h2>' . esc_html( $group_data['group_label'] ) . '</h2>'; 1835 $group_html .= '<div>'; 1836 1837 foreach ( (array) $group_data['items'] as $group_item_id => $group_item_data ) { 1838 $group_html .= '<table>'; 1839 $group_html .= '<tbody>'; 1840 1841 foreach ( (array) $group_item_data as $group_item_datum ) { 1842 $group_html .= '<tr>'; 1843 $group_html .= '<th>' . esc_html( $group_item_datum['name'] ) . '</th>'; 1844 $group_html .= '<td>' . wp_kses( $group_item_datum['value'], $allowed_tags, $allowed_protocols ) . '</td>'; 1845 $group_html .= '</tr>'; 1846 } 1847 1848 $group_html .= '</tbody>'; 1849 $group_html .= '</table>'; 1850 } 1851 1852 $group_html .= '</div>'; 1853 1854 return $group_html; 1855 } 1856 1857 /** 1858 * Generate the personal data export file. 1859 * 1860 * @since 4.9.6 1861 * 1862 * @param int $request_id The export request ID. 1863 */ 1864 function wp_privacy_generate_personal_data_export_file( $request_id ) { 1865 // Maybe make this a cron job instead. 1866 wp_privacy_delete_old_export_files(); 1867 1868 if ( ! class_exists( 'ZipArchive' ) ) { 1869 wp_send_json_error( __( 'Unable to generate export file. ZipArchive not available.' ) ); 1870 } 1871 1872 // Get the request data. 1873 $request = wp_get_user_request_data( $request_id ); 1874 1875 if ( ! $request || 'export_personal_data' !== $request->action_name ) { 1876 wp_send_json_error( __( 'Invalid request ID when generating export file' ) ); 1877 } 1878 1879 $email_address = $request->email; 1880 1881 if ( ! is_email( $email_address ) ) { 1882 wp_send_json_error( __( 'Invalid email address when generating export file' ) ); 1883 } 1884 1885 // Create the exports folder if needed. 1886 $upload_dir = wp_upload_dir(); 1887 $exports_dir = trailingslashit( $upload_dir['basedir'] . '/exports' ); 1888 $exports_url = trailingslashit( $upload_dir['baseurl'] . '/exports' ); 1889 1890 $result = wp_mkdir_p( $exports_dir ); 1891 if ( is_wp_error( $result ) ) { 1892 wp_send_json_error( $result->get_error_message() ); 1893 } 1894 1895 // Protect export folder from browsing. 1896 $index_pathname = $exports_dir . 'index.html'; 1897 if ( ! file_exists( $index_pathname ) ) { 1898 $file = fopen( $index_pathname, 'w' ); 1899 if ( false === $file ) { 1900 wp_send_json_error( __( 'Unable to protect export folder from browsing' ) ); 1901 } 1902 fwrite( $file, 'Silence is golden.' ); 1903 fclose( $file ); 1904 } 1905 1906 $stripped_email = str_replace( '@', '-at-', $email_address ); 1907 $stripped_email = sanitize_title( $stripped_email ); // slugify the email address 1908 $obscura = md5( rand() ); 1909 $file_basename = 'wp-personal-data-file-' . $stripped_email . '-' . $obscura; 1910 $html_report_filename = $file_basename . '.html'; 1911 $html_report_pathname = $exports_dir . $html_report_filename; 1912 $file = fopen( $html_report_pathname, 'w' ); 1913 if ( false === $file ) { 1914 wp_send_json_error( __( 'Unable to open export file (HTML report) for writing' ) ); 1915 } 1916 1917 $title = sprintf( 1918 /* translators: %s: user's e-mail address */ 1919 __( 'Personal Data Export for %s' ), 1920 $email_address 1921 ); 1922 1923 // Open HTML. 1924 fwrite( $file, "<!DOCTYPE html>\n" ); 1925 fwrite( $file, "<html>\n" ); 1926 1927 // Head. 1928 fwrite( $file, "<head>\n" ); 1929 fwrite( $file, "<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />\n" ); 1930 fwrite( $file, "<style type='text/css'>" ); 1931 fwrite( $file, "body { color: black; font-family: Arial, sans-serif; font-size: 11pt; margin: 15px auto; width: 860px; }" ); 1932 fwrite( $file, "table { background: #f0f0f0; border: 1px solid #ddd; margin-bottom: 20px; width: 100%; }" ); 1933 fwrite( $file, "th { padding: 5px; text-align: left; width: 20%; }" ); 1934 fwrite( $file, "td { padding: 5px; }" ); 1935 fwrite( $file, "tr:nth-child(odd) { background-color: #fafafa; }" ); 1936 fwrite( $file, "</style>" ); 1937 fwrite( $file, "<title>" ); 1938 fwrite( $file, esc_html( $title ) ); 1939 fwrite( $file, "</title>" ); 1940 fwrite( $file, "</head>\n" ); 1941 1942 // Body. 1943 fwrite( $file, "<body>\n" ); 1944 1945 // Heading. 1946 fwrite( $file, "<h1>" . esc_html__( 'Personal Data Export' ) . "</h1>" ); 1947 1948 // And now, all the Groups. 1949 $groups = get_post_meta( $request_id, '_export_data_grouped', true ); 1950 1951 // First, build an "About" group on the fly for this report. 1952 $about_group = array( 1953 'group_label' => __( 'About' ), 1954 'items' => array( 1955 'about-1' => array( 1956 array( 1957 'name' => __( 'Report generated for' ), 1958 'value' => $email_address, 1959 ), 1960 array( 1961 'name' => __( 'For site' ), 1962 'value' => get_bloginfo( 'name' ), 1963 ), 1964 array( 1965 'name' => __( 'At URL' ), 1966 'value' => get_bloginfo( 'url' ), 1967 ), 1968 array( 1969 'name' => __( 'On' ), 1970 'value' => current_time( 'mysql' ), 1971 ), 1972 ), 1973 ), 1974 ); 1975 1976 // Merge in the special about group. 1977 $groups = array_merge( array( 'about' => $about_group ), $groups ); 1978 1979 // Now, iterate over every group in $groups and have the formatter render it in HTML. 1980 foreach ( (array) $groups as $group_id => $group_data ) { 1981 fwrite( $file, wp_privacy_generate_personal_data_export_group_html( $group_data ) ); 1982 } 1983 1984 fwrite( $file, "</body>\n" ); 1985 1986 // Close HTML. 1987 fwrite( $file, "</html>\n" ); 1988 fclose( $file ); 1989 1990 // Now, generate the ZIP. 1991 $archive_filename = $file_basename . '.zip'; 1992 $archive_pathname = $exports_dir . $archive_filename; 1993 $archive_url = $exports_url . $archive_filename; 1994 1995 $zip = new ZipArchive; 1996 1997 if ( TRUE === $zip->open( $archive_pathname, ZipArchive::CREATE ) ) { 1998 $zip->addFile( $html_report_pathname, 'index.html' ); 1999 $zip->close(); 2000 } else { 2001 wp_send_json_error( __( 'Unable to open export file (archive) for writing' ) ); 2002 } 2003 2004 // And remove the HTML file. 2005 unlink( $html_report_pathname ); 2006 2007 // Save the export file in the request. 2008 update_post_meta( $request_id, '_export_file_url', $archive_url ); 2009 update_post_meta( $request_id, '_export_file_path', $archive_pathname ); 2010 } 2011 2012 /** 2013 * Send an email to the user with a link to the personal data export file 2014 * 2015 * @since 4.9.6 2016 * 2017 * @param int $request_id The request ID for this personal data export. 2018 * @return true|WP_Error True on success or `WP_Error` on failure. 2019 */ 2020 function wp_privacy_send_personal_data_export_email( $request_id ) { 2021 // Get the request data. 2022 $request = wp_get_user_request_data( $request_id ); 2023 2024 if ( ! $request || 'export_personal_data' !== $request->action_name ) { 2025 return new WP_Error( 'invalid', __( 'Invalid request ID when sending personal data export email.' ) ); 2026 } 2027 2028 /* translators: Do not translate LINK, EMAIL, SITENAME, SITEURL: those are placeholders. */ 2029 $email_text = __( 2030 'Howdy, 2031 2032 Your request for an export of personal data has been completed. You may 2033 download your personal data by clicking on the link below. This link is 2034 good for the next 3 days. 2035 2036 ###LINK### 2037 2038 This email has been sent to ###EMAIL###. 2039 2040 Regards, 2041 All at ###SITENAME### 2042 ###SITEURL###' 2043 ); 2044 2045 /** 2046 * Filters the text of the email sent with a personal data export file. 2047 * 2048 * The following strings have a special meaning and will get replaced dynamically: 2049 * ###LINK### URL of the personal data export file for the user. 2050 * ###EMAIL### The email we are sending to. 2051 * ###SITENAME### The name of the site. 2052 * ###SITEURL### The URL to the site. 2053 * 2054 * @since 4.9.6 2055 * 2056 * @param string $email_text Text in the email. 2057 * @param int $request_id The request ID for this personal data export. 2058 */ 2059 $content = apply_filters( 'wp_privacy_personal_data_email_content', $email_text, $request_id ); 2060 2061 $email_address = $request->email; 2062 $export_file_url = get_post_meta( $request_id, '_export_file_url', true ); 2063 $site_name = is_multisite() ? get_site_option( 'site_name' ) : get_option( 'blogname' ); 2064 $site_url = network_home_url(); 2065 2066 $content = str_replace( '###LINK###', esc_url_raw( $export_file_url ), $content ); 2067 $content = str_replace( '###EMAIL###', $email_address, $content ); 2068 $content = str_replace( '###SITENAME###', wp_specialchars_decode( $site_name, ENT_QUOTES ), $content ); 2069 $content = str_replace( '###SITEURL###', esc_url_raw( $site_url ), $content ); 2070 2071 $mail_success = wp_mail( 2072 $email_address, 2073 sprintf( 2074 __( '[%s] Personal Data Export' ), 2075 wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ) 2076 ), 2077 $content 2078 ); 2079 2080 if ( ! $mail_success ) { 2081 return new WP_Error( 'error', __( 'Unable to send personal data export email.' ) ); 2082 } 2083 2084 return true; 2085 } 2086 2087 /** 2088 * Intercept personal data exporter page ajax responses in order to assemble the personal data export file. 2089 * @see wp_privacy_personal_data_export_page 2090 * @since 4.9.6 2091 * 2092 * @param array $response The response from the personal data exporter for the given page. 2093 * @param int $exporter_index The index of the personal data exporter. Begins at 1. 2094 * @param string $email_address The email address of the user whose personal data this is. 2095 * @param int $page The page of personal data for this exporter. Begins at 1. 2096 * @param int $request_id The request ID for this personal data export. 2097 * @param bool $send_as_email Whether the final results of the export should be emailed to the user. 2098 * @return array The filtered response. 2099 */ 2100 function wp_privacy_process_personal_data_export_page( $response, $exporter_index, $email_address, $page, $request_id, $send_as_email ) { 2101 /* Do some simple checks on the shape of the response from the exporter. 2102 * If the exporter response is malformed, don't attempt to consume it - let it 2103 * pass through to generate a warning to the user by default ajax processing. 2104 */ 2105 if ( ! is_array( $response ) ) { 2106 return $response; 2107 } 2108 2109 if ( ! array_key_exists( 'done', $response ) ) { 2110 return $response; 2111 } 2112 2113 if ( ! array_key_exists( 'data', $response ) ) { 2114 return $response; 2115 } 2116 2117 if ( ! is_array( $response['data'] ) ) { 2118 return $response; 2119 } 2120 2121 // Get the request data. 2122 $request = wp_get_user_request_data( $request_id ); 2123 2124 if ( ! $request || 'export_personal_data' !== $request->action_name ) { 2125 wp_send_json_error( __( 'Invalid request ID when merging exporter data' ) ); 2126 } 2127 2128 $export_data = array(); 2129 2130 // First exporter, first page? Reset the report data accumulation array. 2131 if ( 1 === $exporter_index && 1 === $page ) { 2132 update_post_meta( $request_id, '_export_data_raw', $export_data ); 2133 } else { 2134 $export_data = get_post_meta( $request_id, '_export_data_raw', true ); 2135 } 2136 2137 // Now, merge the data from the exporter response into the data we have accumulated already. 2138 $export_data = array_merge( $export_data, $response['data'] ); 2139 update_post_meta( $request_id, '_export_data_raw', $export_data ); 2140 2141 // If we are not yet on the last page of the last exporter, return now. 2142 $exporters = apply_filters( 'wp_privacy_personal_data_exporters', array() ); 2143 $is_last_exporter = $exporter_index === count( $exporters ); 2144 $exporter_done = $response['done']; 2145 if ( ! $is_last_exporter || ! $exporter_done ) { 2146 return $response; 2147 } 2148 2149 // Last exporter, last page - let's prepare the export file. 2150 2151 // First we need to re-organize the raw data hierarchically in groups and items. 2152 $groups = array(); 2153 foreach ( (array) $export_data as $export_datum ) { 2154 $group_id = $export_datum['group_id']; 2155 $group_label = $export_datum['group_label']; 2156 if ( ! array_key_exists( $group_id, $groups ) ) { 2157 $groups[ $group_id ] = array( 2158 'group_label' => $group_label, 2159 'items' => array(), 2160 ); 2161 } 2162 2163 $item_id = $export_datum['item_id']; 2164 if ( ! array_key_exists( $item_id, $groups[ $group_id ]['items'] ) ) { 2165 $groups[ $group_id ]['items'][ $item_id ] = array(); 2166 } 2167 2168 $old_item_data = $groups[ $group_id ]['items'][ $item_id ]; 2169 $merged_item_data = array_merge( $export_datum['data'], $old_item_data ); 2170 $groups[ $group_id ]['items'][ $item_id ] = $merged_item_data; 2171 } 2172 2173 // Then save the grouped data into the request. 2174 delete_post_meta( $request_id, '_export_data_raw' ); 2175 update_post_meta( $request_id, '_export_data_grouped', $groups ); 2176 2177 // And now, generate the export file, cleaning up any previous file 2178 $export_path = get_post_meta( $request_id, '_export_file_path', true ); 2179 if ( ! empty( $export_path ) ) { 2180 delete_post_meta( $request_id, '_export_file_path' ); 2181 @unlink( $export_path ); 2182 } 2183 delete_post_meta( $request_id, '_export_file_url' ); 2184 2185 // Generate the export file from the collected, grouped personal data. 2186 do_action( 'wp_privacy_personal_data_export_file', $request_id ); 2187 2188 // Clear the grouped data now that it is no longer needed. 2189 delete_post_meta( $request_id, '_export_data_grouped' ); 2190 2191 // If the destination is email, send it now. 2192 if ( $send_as_email ) { 2193 $mail_success = wp_privacy_send_personal_data_export_email( $request_id ); 2194 if ( is_wp_error( $mail_success ) ) { 2195 wp_send_json_error( $mail_success->get_error_message() ); 2196 } 2197 } else { 2198 // Modify the response to include the URL of the export file so the browser can fetch it. 2199 $export_file_url = get_post_meta( $request_id, '_export_file_url', true ); 2200 if ( ! empty( $export_file_url ) ) { 2201 $response['url'] = $export_file_url; 2202 } 2203 } 2204 2205 // Update the request to completed state. 2206 _wp_privacy_completed_request( $request_id ); 2207 2208 return $response; 2209 } 2210 2211 /** 2212 * Cleans up export files older than three days old. 2213 * 2214 * @since 4.9.6 2215 */ 2216 function wp_privacy_delete_old_export_files() { 2217 $upload_dir = wp_upload_dir(); 2218 $exports_dir = trailingslashit( $upload_dir['basedir'] . '/exports' ); 2219 $export_files = list_files( $exports_dir ); 2220 2221 foreach( (array) $export_files as $export_file ) { 2222 $file_age_in_seconds = time() - filemtime( $export_file ); 2223 2224 if ( 3 * DAY_IN_SECONDS < $file_age_in_seconds ) { 2225 @unlink( $export_file ); 2226 } 2227 } 2228 } -
branches/4.9/src/wp-admin/includes/user.php
r43086 r43092 620 620 'privacy_action_email_retry', 621 621 __( 'Confirmation request re-resent successfully.' ), 622 'updated'623 );624 }625 626 } elseif ( isset( $_POST['export_personal_data_email_send'] ) ) { // WPCS: input var ok.627 check_admin_referer( 'bulk-privacy_requests' );628 629 $request_id = absint( current( array_keys( (array) wp_unslash( $_POST['export_personal_data_email_send'] ) ) ) ); // WPCS: input var ok, sanitization ok.630 $result = false;631 632 /**633 * TODO: Email the data to the user here.634 */635 636 if ( is_wp_error( $result ) ) {637 add_settings_error(638 'export_personal_data_email_send',639 'export_personal_data_email_send',640 $result->get_error_message(),641 'error'642 );643 } else {644 _wp_privacy_completed_request( $request_id );645 add_settings_error(646 'export_personal_data_email_send',647 'export_personal_data_email_send',648 __( 'Personal data was sent to the user successfully.' ),649 622 'updated' 650 623 ); … … 779 752 _wp_personal_data_cleanup_requests(); 780 753 754 // "Borrow" xfn.js for now so we don't have to create new files. 755 wp_enqueue_script( 'xfn' ); 756 781 757 $requests_table = new WP_Privacy_Data_Export_Requests_Table( array( 782 758 'plural' => 'privacy_requests', … … 1321 1297 $nonce = wp_create_nonce( 'wp-privacy-export-personal-data-' . $request_id ); 1322 1298 1323 $download_data_markup = '<div class=" download_personal_data" ' .1299 $download_data_markup = '<div class="export_personal_data" ' . 1324 1300 'data-exporters-count="' . esc_attr( $exporters_count ) . '" ' . 1325 1301 'data-request-id="' . esc_attr( $request_id ) . '" ' . … … 1327 1303 '">'; 1328 1304 1329 $download_data_markup .= '<span class="download_personal_data_idle"><a href="#" >' . __( 'Download Personal Data' ) . '</a></span>' . 1330 '<span style="display:none" class="download_personal_data_processing" >' . __( 'Downloading Data...' ) . '</span>' . 1331 '<span style="display:none" class="download_personal_data_failed">' . __( 'Download Failed!' ) . ' <a href="#" >' . __( 'Retry' ) . '</a></span>'; 1305 $download_data_markup .= '<span class="export_personal_data_idle"><a href="#" >' . __( 'Download Personal Data' ) . '</a></span>' . 1306 '<span style="display:none" class="export_personal_data_processing" >' . __( 'Downloading Data...' ) . '</span>' . 1307 '<span style="display:none" class="export_personal_data_success"><a href="#" >' . __( 'Download Personal Data Again' ) . '</a></span>' . 1308 '<span style="display:none" class="export_personal_data_failed">' . __( 'Download Failed!' ) . ' <a href="#" >' . __( 'Retry' ) . '</a></span>'; 1309 1310 $download_data_markup .= '</div>'; 1332 1311 1333 1312 $row_actions = array( … … 1353 1332 break; 1354 1333 case 'request-confirmed': 1355 // TODO Complete in follow on patch. 1334 $exporters = apply_filters( 'wp_privacy_personal_data_exporters', array() ); 1335 $exporters_count = count( $exporters ); 1336 $request_id = $item->ID; 1337 $nonce = wp_create_nonce( 'wp-privacy-export-personal-data-' . $request_id ); 1338 1339 echo '<div class="export_personal_data" ' . 1340 'data-send-as-email="1" ' . 1341 'data-exporters-count="' . esc_attr( $exporters_count ) . '" ' . 1342 'data-request-id="' . esc_attr( $request_id ) . '" ' . 1343 'data-nonce="' . esc_attr( $nonce ) . 1344 '">'; 1345 1346 ?> 1347 <span class="export_personal_data_idle"><a class="button" href="#" ><?php _e( 'Email Data' ); ?></a></span> 1348 <span style="display:none" class="export_personal_data_processing button updating-message" ><?php _e( 'Sending Email...' ); ?></span> 1349 <span style="display:none" class="export_personal_data_success success-message" ><?php _e( 'Email Sent!' ); ?></span> 1350 <span style="display:none" class="export_personal_data_failed"><?php _e( 'Email Failed!' ); ?> <a class="button" href="#" ><?php _e( 'Retry' ); ?></a></span> 1351 <?php 1352 1353 echo '</div>'; 1356 1354 break; 1357 1355 case 'request-failed': … … 1421 1419 '<span style="display:none" class="remove_personal_data_failed">' . __( 'Force Remove Failed!' ) . ' <a href="#" >' . __( 'Retry' ) . '</a></span>'; 1422 1420 1421 $remove_data_markup .= '</div>'; 1422 1423 1423 $row_actions = array( 1424 1424 'remove_data' => $remove_data_markup, … … 1461 1461 <span style="display:none" class="remove_personal_data_failed"><?php _e( 'Removing Data Failed!' ); ?> <a class="button" href="#" ><?php _e( 'Retry' ); ?></a></span> 1462 1462 <?php 1463 1464 echo '</div>'; 1463 1465 1464 1466 break; -
branches/4.9/src/wp-admin/js/xfn.js
r43080 r43092 18 18 19 19 // Privacy request action handling 20 21 20 jQuery( document ).ready( function( $ ) { 22 21 var strings = window.privacyToolsL10n || {}; … … 35 34 function appendResultsAfterRow( $requestRow, classes, summaryMessage, additionalMessages ) { 36 35 clearResultsAfterRow( $requestRow ); 36 37 var itemList = ''; 37 38 if ( additionalMessages.length ) { 38 // TODO - render additionalMessages after the summaryMessage 39 $.each( additionalMessages, function( index, value ) { 40 itemList = itemList + '<li>' + value + '</li>'; 41 } ); 42 itemList = '<ul>' + itemList + '</ul>'; 39 43 } 40 44 41 45 $requestRow.after( function() { 42 return '<tr class="request-results"><td colspan="5"><div class="notice inline notice-alt ' + classes + '"><p>' + 43 summaryMessage + 44 '</p></div></td></tr>'; 46 return '<tr class="request-results"><td colspan="5">' + 47 '<div class="notice inline notice-alt ' + classes + '">' + 48 '<p>' + summaryMessage + '</p>' + 49 itemList + 50 '</div>' + 51 '</td>' + 52 '</tr>'; 45 53 } ); 46 54 } 55 56 $( '.export_personal_data a' ).click( function( event ) { 57 event.preventDefault(); 58 event.stopPropagation(); 59 60 var $this = $( this ); 61 var $action = $this.parents( '.export_personal_data' ); 62 var $requestRow = $this.parents( 'tr' ); 63 var requestID = $action.data( 'request-id' ); 64 var nonce = $action.data( 'nonce' ); 65 var exportersCount = $action.data( 'exporters-count' ); 66 var sendAsEmail = $action.data( 'send-as-email' ) ? true : false; 67 68 $action.blur(); 69 clearResultsAfterRow( $requestRow ); 70 71 function on_export_done_success( zipUrl ) { 72 set_action_state( $action, 'export_personal_data_success' ); 73 if ( 'undefined' !== typeof zipUrl ) { 74 window.location = zipUrl; 75 } else if ( ! sendAsEmail ) { 76 on_export_failure( strings.noExportFile ); 77 } 78 } 79 80 function on_export_failure( errorMessage ) { 81 set_action_state( $action, 'export_personal_data_failed' ); 82 if ( errorMessage ) { 83 appendResultsAfterRow( $requestRow, 'notice-error', strings.exportError, [ errorMessage ] ); 84 } 85 } 86 87 function do_next_export( exporterIndex, pageIndex ) { 88 $.ajax( 89 { 90 url: window.ajaxurl, 91 data: { 92 action: 'wp-privacy-export-personal-data', 93 exporter: exporterIndex, 94 id: requestID, 95 page: pageIndex, 96 security: nonce, 97 sendAsEmail: sendAsEmail 98 }, 99 method: 'post' 100 } 101 ).done( function( response ) { 102 if ( ! response.success ) { 103 // e.g. invalid request ID 104 on_export_failure( response.data ); 105 return; 106 } 107 var responseData = response.data; 108 if ( ! responseData.done ) { 109 setTimeout( do_next_export( exporterIndex, pageIndex + 1 ) ); 110 } else { 111 if ( exporterIndex < exportersCount ) { 112 setTimeout( do_next_export( exporterIndex + 1, 1 ) ); 113 } else { 114 on_export_done_success( responseData.url ); 115 } 116 } 117 } ).fail( function( jqxhr, textStatus, error ) { 118 // e.g. Nonce failure 119 on_export_failure( error ); 120 } ); 121 } 122 123 // And now, let's begin 124 set_action_state( $action, 'export_personal_data_processing' ); 125 do_next_export( 1, 1 ); 126 } ); 47 127 48 128 $( '.remove_personal_data a' ).click( function( event ) { … … 88 168 function on_erasure_failure() { 89 169 set_action_state( $action, 'remove_personal_data_failed' ); 90 appendResultsAfterRow( $requestRow, 'notice-error', strings. anErrorOccurred, [] );170 appendResultsAfterRow( $requestRow, 'notice-error', strings.removalError, [] ); 91 171 } 92 172 -
branches/4.9/src/wp-includes/comment.php
r43080 r43092 3224 3224 case 'comment_link': 3225 3225 $value = get_comment_link( $comment->comment_ID ); 3226 $value = '<a href="' . $value . '" target="_blank" rel="noreferrer noopener">' . $value . '</a>'; 3226 3227 break; 3227 3228 } -
branches/4.9/src/wp-includes/script-loader.php
r43075 r43092 666 666 'noneRemoved' => __( 'Personal data was found for this user but was not removed.' ), 667 667 'someNotRemoved' => __( 'Personal data was found for this user but some of the personal data found was not removed.' ), 668 'anErrorOccurred' => __( 'An error occurred while attempting to find and remove personal data.' ), 668 'removalError' => __( 'An error occurred while attempting to find and remove personal data.' ), 669 'noExportFile' => __( 'No personal data export file was generated.' ), 670 'exportError' => __( 'An error occurred while attempting to export personal data.' ), 669 671 ) 670 672 ); -
branches/4.9/src/wp-includes/user.php
r43084 r43092 3070 3070 * 3071 3071 * @param int $request_id Request ID to get data about. 3072 * @return array|false3072 * @return WP_User_Request|false 3073 3073 */ 3074 3074 function wp_get_user_request_data( $request_id ) {
Note: See TracChangeset
for help on using the changeset viewer.