WordPress.org

Make WordPress Core

Changeset 47146


Ignore:
Timestamp:
01/31/2020 01:34:17 AM (4 months ago)
Author:
SergeyBiryukov
Message:

Privacy: Introduce a JSON file into the personal data export.

The produced ZIP archive will now include an export.json file along with the current index.html.

Props xkon.
Fixes #49029. See #46424.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/privacy-tools.php

    r47144 r47146  
    325325    $html_report_filename = wp_unique_filename( $exports_dir, $file_basename . '.html' );
    326326    $html_report_pathname = wp_normalize_path( $exports_dir . $html_report_filename );
    327     $file                 = fopen( $html_report_pathname, 'w' );
    328     if ( false === $file ) {
    329         wp_send_json_error( __( 'Unable to open export file (HTML report) for writing.' ) );
    330     }
    331 
     327    $json_report_filename = $file_basename . '.json';
     328    $json_report_pathname = wp_normalize_path( $exports_dir . $json_report_filename );
     329
     330    /*
     331     * Gather general data needed.
     332     */
     333
     334    // Title.
    332335    $title = sprintf(
    333336        /* translators: %s: User's email address. */
     
    335338        $email_address
    336339    );
    337 
    338     // Open HTML.
    339     fwrite( $file, "<!DOCTYPE html>\n" );
    340     fwrite( $file, "<html>\n" );
    341 
    342     // Head.
    343     fwrite( $file, "<head>\n" );
    344     fwrite( $file, "<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />\n" );
    345     fwrite( $file, "<style type='text/css'>" );
    346     fwrite( $file, 'body { color: black; font-family: Arial, sans-serif; font-size: 11pt; margin: 15px auto; width: 860px; }' );
    347     fwrite( $file, 'table { background: #f0f0f0; border: 1px solid #ddd; margin-bottom: 20px; width: 100%; }' );
    348     fwrite( $file, 'th { padding: 5px; text-align: left; width: 20%; }' );
    349     fwrite( $file, 'td { padding: 5px; }' );
    350     fwrite( $file, 'tr:nth-child(odd) { background-color: #fafafa; }' );
    351     fwrite( $file, '</style>' );
    352     fwrite( $file, '<title>' );
    353     fwrite( $file, esc_html( $title ) );
    354     fwrite( $file, '</title>' );
    355     fwrite( $file, "</head>\n" );
    356 
    357     // Body.
    358     fwrite( $file, "<body>\n" );
    359 
    360     // Heading.
    361     fwrite( $file, '<h1>' . esc_html__( 'Personal Data Export' ) . '</h1>' );
    362340
    363341    // And now, all the Groups.
     
    395373    $groups = array_merge( array( 'about' => $about_group ), $groups );
    396374
     375    // Convert the groups to JSON format.
     376    $groups_json = wp_json_encode( $groups );
     377
     378    /*
     379     * Handle the JSON export.
     380     */
     381    $file = fopen( $json_report_pathname, 'w' );
     382
     383    if ( false === $file ) {
     384        wp_send_json_error( __( 'Unable to open export file (JSON report) for writing.' ) );
     385    }
     386
     387    fwrite( $file, '{' );
     388    fwrite( $file, '"' . $title . '":' );
     389    fwrite( $file, $groups_json );
     390    fwrite( $file, '}' );
     391    fclose( $file );
     392
     393    /*
     394     * Handle the HTML export.
     395     */
     396    $file = fopen( $html_report_pathname, 'w' );
     397
     398    if ( false === $file ) {
     399        wp_send_json_error( __( 'Unable to open export file (HTML report) for writing.' ) );
     400    }
     401
     402    fwrite( $file, "<!DOCTYPE html>\n" );
     403    fwrite( $file, "<html>\n" );
     404    fwrite( $file, "<head>\n" );
     405    fwrite( $file, "<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />\n" );
     406    fwrite( $file, "<style type='text/css'>" );
     407    fwrite( $file, 'body { color: black; font-family: Arial, sans-serif; font-size: 11pt; margin: 15px auto; width: 860px; }' );
     408    fwrite( $file, 'table { background: #f0f0f0; border: 1px solid #ddd; margin-bottom: 20px; width: 100%; }' );
     409    fwrite( $file, 'th { padding: 5px; text-align: left; width: 20%; }' );
     410    fwrite( $file, 'td { padding: 5px; }' );
     411    fwrite( $file, 'tr:nth-child(odd) { background-color: #fafafa; }' );
     412    fwrite( $file, '</style>' );
     413    fwrite( $file, '<title>' );
     414    fwrite( $file, esc_html( $title ) );
     415    fwrite( $file, '</title>' );
     416    fwrite( $file, "</head>\n" );
     417    fwrite( $file, "<body>\n" );
     418    fwrite( $file, '<h1>' . esc_html__( 'Personal Data Export' ) . '</h1>' );
     419
    397420    // Now, iterate over every group in $groups and have the formatter render it in HTML.
    398421    foreach ( (array) $groups as $group_id => $group_data ) {
     
    401424
    402425    fwrite( $file, "</body>\n" );
    403 
    404     // Close HTML.
    405426    fwrite( $file, "</html>\n" );
    406427    fclose( $file );
     
    432453    $zip = new ZipArchive;
    433454    if ( true === $zip->open( $archive_pathname, ZipArchive::CREATE ) ) {
     455        if ( ! $zip->addFile( $json_report_pathname, 'export.json' ) ) {
     456            $error = __( 'Unable to add data to JSON file.' );
     457        }
     458
    434459        if ( ! $zip->addFile( $html_report_pathname, 'index.html' ) ) {
    435             $error = __( 'Unable to add data to export file.' );
     460            $error = __( 'Unable to add data to HTML file.' );
    436461        }
    437462
     
    449474             * @param int    $request_id           The export request ID.
    450475             */
    451             do_action( 'wp_privacy_personal_data_export_file_created', $archive_pathname, $archive_url, $html_report_pathname, $request_id );
     476            do_action( 'wp_privacy_personal_data_export_file_created', $archive_pathname, $archive_url, $html_report_pathname, $request_id, $json_report_pathname );
    452477        }
    453478    } else {
     
    455480    }
    456481
    457     // And remove the HTML file.
     482    // Remove the JSON file.
     483    unlink( $json_report_pathname );
     484
     485    // Remove the HTML file.
    458486    unlink( $html_report_pathname );
    459487
  • trunk/tests/phpunit/tests/privacy/wpPrivacyGeneratePersonalDataExportFile.php

    r46586 r47146  
    238238
    239239    /**
    240      * Test the export file has all the expected parts.
    241      *
    242      * @ticket 44233
    243      */
    244     public function test_contents() {
     240     * Test the export HTML file has all the expected parts.
     241     *
     242     * @ticket 44233
     243     */
     244    public function test_html_contents() {
    245245        $this->expectOutputString( '' );
    246246        wp_privacy_generate_personal_data_export_file( self::$export_request_id );
     
    265265        $this->assertContains( $request->email, $report_contents );
    266266    }
     267
     268    /**
     269     * Test the export JSON file has all the expected parts.
     270     *
     271     * @ticket 49029
     272     */
     273    public function test_json_contents() {
     274        $this->expectOutputString( '' );
     275        wp_privacy_generate_personal_data_export_file( self::$export_request_id );
     276        $this->assertTrue( file_exists( $this->export_file_name ) );
     277
     278        $report_dir = trailingslashit( self::$exports_dir . 'test_contents' );
     279        mkdir( $report_dir );
     280
     281        $zip        = new ZipArchive();
     282        $opened_zip = $zip->open( $this->export_file_name );
     283        $this->assertTrue( $opened_zip );
     284
     285        $zip->extractTo( $report_dir );
     286        $zip->close();
     287
     288        $request = wp_get_user_request_data( self::$export_request_id );
     289
     290        $this->assertTrue( file_exists( $report_dir . 'export.json' ) );
     291
     292        $report_contents_json = file_get_contents( $report_dir . 'export.json' );
     293
     294        $this->assertContains( '"Personal Data Export for ' . $request->email . '"', $report_contents_json );
     295        $this->assertContains( '"about"', $report_contents_json );
     296    }
    267297}
Note: See TracChangeset for help on using the changeset viewer.