WordPress.org

Make WordPress Core

Ticket #43551: 43551.diff

File 43551.diff, 6.4 KB (added by allendav, 4 years ago)

Work in progress

  • src/wp-admin/includes/admin-filters.php

     
    128128add_action( 'upgrader_process_complete', 'wp_version_check', 10, 0 );
    129129add_action( 'upgrader_process_complete', 'wp_update_plugins', 10, 0 );
    130130add_action( 'upgrader_process_complete', 'wp_update_themes', 10, 0 );
     131
     132// Privacy hooks
     133add_action( 'admin_init', 'wp_privacy_delete_old_export_files' );
     134add_filter( 'wp_privacy_personal_data_export_page', 'wp_privacy_process_personal_data_export_page', 10, 4 );
  • src/wp-admin/includes/file.php

     
    19341934        </div>
    19351935        <?php
    19361936}
     1937
     1938// TODO phpDocs
     1939function wp_privacy_generate_personal_data_export( $exports_dir, $email_address, $personal_data ) {
     1940
     1941        // TODO Instead of HTML, return a ZIP containing the HTML and the attachments
     1942        $timestamp = current_time( 'timestamp' );
     1943        $index_filename = 'wp-personal-data-export-' . md5( $email_address ) . '-' . md5( $timestamp ) . '.html';
     1944
     1945        $index_path = trailingslashit( $exports_dir ) . $index_filename;
     1946        $file = fopen( $index_path, 'w' );
     1947        // TODO catch fopen error
     1948
     1949        fwrite( $file, "<!DOCTYPE html>\n" );
     1950        fwrite( $file, "<html>\n" );
     1951        fwrite( $file, "<head>\n" );
     1952
     1953        // TODO title using email address
     1954
     1955        fwrite( $file, "</head>\n" );
     1956        fwrite( $file, "<body>\n" );
     1957
     1958        // TODO heading using email address and possibly gravatar
     1959        // TODO heading should also include date/time generated and for what site
     1960
     1961        fwrite( $file, "<table>\n" );
     1962        fwrite( $file, "<tbody>\n" );
     1963
     1964        foreach( (array) $personal_data as $personal_datum ) {
     1965                fwrite( $file, "<tr>\n" );
     1966                fwrite( $file, "<td>" );
     1967                fwrite( $file, esc_html( $personal_datum['name'] ) );
     1968                fwrite( $file, "</td>\n" );
     1969                fwrite( $file, "<td>" );
     1970                // TODO kses the value
     1971                // TODO linkify filepaths from wp-content/uploads
     1972                fwrite( $file, nl2br( $personal_datum['value'] ) );
     1973                fwrite( $file, "</td>" );
     1974                fwrite( $file, "</tr>\n" );
     1975        }
     1976
     1977        fwrite( $file, "</tbody>\n" );
     1978        fwrite( $file, "</table>\n" );
     1979        fwrite( $file, "</body>\n" );
     1980        fwrite( $file, "</html>\n" );
     1981        fclose( $file );
     1982
     1983        // Now, generate the ZIP
     1984        $archive_filename = 'wp-personal-data-export-' . md5( $email_address ) . '-' . md5( $timestamp ) . '.zip';
     1985        $archive_path = trailingslashit( $exports_dir ) . $archive_filename;
     1986
     1987        $zip = new ZipArchive;
     1988        // TODO test for no ZipArchive to work with
     1989
     1990        if ( TRUE === $zip->open( $archive_path, ZipArchive::CREATE ) ) {
     1991                $zip->addFile( $index_path, 'index.html' );
     1992                // TODO - add things referenced in wp-content/uploads
     1993                $zip->close();
     1994        } else {
     1995                error_log( "unable to open zip for creation" );
     1996                // TODO handle error here
     1997        }
     1998
     1999        // And remove the HTML file
     2000        unlink( $index_path );
     2001
     2002        return(
     2003                array(
     2004                        'timestamp' => $timestamp,
     2005                        'filename' => $archive_filename,
     2006                )
     2007        );
     2008}
     2009
     2010// TODO phpDocs
     2011function wp_privacy_process_personal_data_export_page( $response, $exporter_index, $email_address, $page ) {
     2012
     2013        // Housekeeping
     2014        $upload_dir  = wp_upload_dir();
     2015        $exports_dir = $upload_dir['basedir'] . '/exports';
     2016        $exports_url = $upload_dir['baseurl'] . '/exports';
     2017
     2018        // Create the exports folder if needed
     2019        $result = wp_mkdir_p( $exports_dir );
     2020        if ( is_wp_error( $result ) ) {
     2021                return $result;
     2022        }
     2023
     2024        // TODO Make sure the exports folder is protected (htaccess, index)
     2025
     2026        // Generate a export file option key from the email address
     2027        $export_file_option = '_wp_privacy_export_file_' . md5( $email_address );
     2028
     2029        // See if we have an export URL cached for this user already
     2030        $export_file_details = get_site_option( $export_file_option, '', false );
     2031
     2032        // And if we do, short circuit the export and send the path back instead
     2033        if ( ! empty( $export_file_details ) ) {
     2034                $pieces = explode( ':', $export_file_details ); // path:timestamp
     2035                $export_file_path = trailingslashit( $exports_dir ) . $pieces[0];
     2036
     2037                if ( file_exists( $export_file_path ) ) {
     2038                        return(
     2039                                array(
     2040                                        'data' => array(),
     2041                                        'done' => true,
     2042                                        'url'  => $pieces[0],
     2043                                )
     2044                        );
     2045                }
     2046
     2047                // No file? Delete the option and continue building the export
     2048                delete_site_option( $export_file_option );
     2049        }
     2050
     2051        // Generate a (temporary) data storage option key from the email address
     2052        $export_data_option = '_wp_privacy_export_data_' . md5( $email_address );
     2053
     2054        // First page of first exporter? Prepare/clear the option where we will assemble all the responses
     2055        if ( 0 === $exporter_index && 0 === $page ) {
     2056                update_site_option( $export_data_option, array() );
     2057        }
     2058
     2059        // Grab whatever data has already been collected on previous exporters and/or pages
     2060        $export_data = get_site_option( $export_data_option, array() );
     2061
     2062        // Does the response include data? If so, add this response's data to all the data we have received so far
     2063        // TODO - make 43438 enforce the data/done/url shape?
     2064        // TODO - enforce data as a numeric (not associative) array
     2065        $exporter_page_data = $response['data'];
     2066        if ( ! empty( $exporter_page_data ) && is_array( $exporter_page_data ) ) {
     2067                $export_data = array_merge( $export_data, $exporter_page_data );
     2068                update_site_option( $export_data_option, $export_data );
     2069        }
     2070
     2071        // Are we on the last exporter, and did that export say it was done? If not, return now
     2072        // so we can continue to collect data for export
     2073        $exporters = apply_filters( 'wp_privacy_personal_data_exporters', array() );
     2074        $is_last_exporter = $exporter_index === count( $exporters ) - 1;
     2075        $exporter_done = $response['done'];
     2076        if ( ! $is_last_exporter || ! $exporter_done ) {
     2077                return $response;
     2078        }
     2079
     2080        // TODO de-repetitive-ize the data
     2081
     2082        // Generate the export
     2083        $result = wp_privacy_generate_personal_data_export( $exports_dir, $email_address, $export_data );
     2084        if ( is_wp_error( $result ) ) {
     2085                return $result;
     2086        }
     2087
     2088        // Get the timestamp and filename from the export
     2089        $timestamp = $result['timestamp'];
     2090        $filename = $result['filename'];
     2091
     2092        // Build the URL for the file
     2093        $export_url = trailingslashit( $exports_url ) . $filename;
     2094
     2095        // Modify the response to include the URL of the export file
     2096        $response['url'] = $export_url;
     2097
     2098        // TODO Save the export file in an option for safekeeping
     2099
     2100        return $response;
     2101}
     2102
     2103function wp_privacy_delete_old_export_files() {
     2104
     2105        // TODO delete old export files and their options
     2106
     2107}