diff --git a/src/wp-admin/includes/privacy-tools.php b/src/wp-admin/includes/privacy-tools.php
index b547468184..81ce65baf4 100644
|
a
|
b
|
function _wp_personal_data_cleanup_requests() { |
| 215 | 215 | * Generate a single group for the personal data export report. |
| 216 | 216 | * |
| 217 | 217 | * @since 4.9.6 |
| | 218 | * @since 5.4.0 Added $group_id to support the TOC implementation. |
| 218 | 219 | * |
| 219 | 220 | * @param array $group_data { |
| 220 | 221 | * The group data to render. |
| … |
… |
function _wp_personal_data_cleanup_requests() { |
| 233 | 234 | * } |
| 234 | 235 | * @return string The HTML for this group and its items. |
| 235 | 236 | */ |
| 236 | | function wp_privacy_generate_personal_data_export_group_html( $group_data ) { |
| 237 | | $group_html = '<h2>'; |
| | 237 | function wp_privacy_generate_personal_data_export_group_html( $group_data, $group_id = '' ) { |
| | 238 | $group_id_attr = sanitize_title_with_dashes( $group_data['group_label'] . '-' . $group_id ); |
| | 239 | |
| | 240 | $group_html = '<h2 id="' . esc_attr( $group_id_attr ) . '">'; |
| 238 | 241 | $group_html .= esc_html( $group_data['group_label'] ); |
| 239 | 242 | |
| 240 | 243 | $items_count = count( (array) $group_data['items'] ); |
| … |
… |
function wp_privacy_generate_personal_data_export_group_html( $group_data ) { |
| 271 | 274 | $group_html .= '</table>'; |
| 272 | 275 | } |
| 273 | 276 | |
| | 277 | $group_html .= '<div class="return_to_top">'; |
| | 278 | $group_html .= '<a href="#top">' . esc_html__( '↑ Return to top' ) . '</a>'; |
| | 279 | $group_html .= '</div>'; |
| | 280 | |
| 274 | 281 | $group_html .= '</div>'; |
| 275 | 282 | |
| 276 | 283 | return $group_html; |
| … |
… |
function wp_privacy_generate_personal_data_export_file( $request_id ) { |
| 409 | 416 | fwrite( $file, 'th { padding: 5px; text-align: left; width: 20%; }' ); |
| 410 | 417 | fwrite( $file, 'td { padding: 5px; }' ); |
| 411 | 418 | fwrite( $file, 'tr:nth-child(odd) { background-color: #fafafa; }' ); |
| | 419 | fwrite( $file, '.return_to_top { text-align:right; }' ); |
| 412 | 420 | fwrite( $file, '</style>' ); |
| 413 | 421 | fwrite( $file, '<title>' ); |
| 414 | 422 | fwrite( $file, esc_html( $title ) ); |
| 415 | 423 | fwrite( $file, '</title>' ); |
| 416 | 424 | fwrite( $file, "</head>\n" ); |
| 417 | 425 | fwrite( $file, "<body>\n" ); |
| 418 | | fwrite( $file, '<h1>' . esc_html__( 'Personal Data Export' ) . '</h1>' ); |
| | 426 | fwrite( $file, '<h1 id="top">' . esc_html__( 'Personal Data Export' ) . '</h1>' ); |
| | 427 | |
| | 428 | // Create TOC. |
| | 429 | if ( count( $groups ) > 1 ) { |
| | 430 | fwrite( $file, '<div id="table_of_contents">' ); |
| | 431 | fwrite( $file, '<h2>' . esc_html__( 'Table of Contents' ) . '</h2>' ); |
| | 432 | fwrite( $file, '<ul>' ); |
| | 433 | foreach ( (array) $groups as $group_id => $group_data ) { |
| | 434 | $group_id_attr = sanitize_title_with_dashes( $group_data['group_label'] . '-' . $group_id ); |
| | 435 | fwrite( $file, '<li>' ); |
| | 436 | fwrite( $file, '<a href="#' . esc_attr( $group_id_attr ) . '">' . esc_html( $group_data['group_label'] ) . '</a>' ); |
| | 437 | fwrite( $file, '</li>' ); |
| | 438 | } |
| | 439 | fwrite( $file, '</ul>' ); |
| | 440 | fwrite( $file, '</div>' ); |
| | 441 | } |
| 419 | 442 | |
| 420 | 443 | // Now, iterate over every group in $groups and have the formatter render it in HTML. |
| 421 | 444 | foreach ( (array) $groups as $group_id => $group_data ) { |
| 422 | | fwrite( $file, wp_privacy_generate_personal_data_export_group_html( $group_data ) ); |
| | 445 | fwrite( $file, wp_privacy_generate_personal_data_export_group_html( $group_data, $group_id ) ); |
| 423 | 446 | } |
| 424 | 447 | |
| 425 | 448 | fwrite( $file, "</body>\n" ); |
diff --git a/tests/phpunit/tests/privacy/wpPrivacyGeneratePersonalDataExportFile.php b/tests/phpunit/tests/privacy/wpPrivacyGeneratePersonalDataExportFile.php
index c38007f498..ec1cbceb36 100644
|
a
|
b
|
class Tests_Privacy_WpPrivacyGeneratePersonalDataExportFile extends WP_UnitTestC |
| 260 | 260 | $report_contents = file_get_contents( $report_dir . 'index.html' ); |
| 261 | 261 | $request = wp_get_user_request_data( self::$export_request_id ); |
| 262 | 262 | |
| 263 | | $this->assertContains( '<h1>Personal Data Export</h1>', $report_contents ); |
| 264 | | $this->assertContains( '<h2>About</h2>', $report_contents ); |
| | 263 | $this->assertContains( '<h1 id="top">Personal Data Export</h1>', $report_contents ); |
| | 264 | $this->assertContains( '<h2 id="about-about">About</h2>', $report_contents ); |
| 265 | 265 | $this->assertContains( $request->email, $report_contents ); |
| 266 | 266 | } |
| 267 | 267 | |
diff --git a/tests/phpunit/tests/privacy/wpPrivacyGeneratePersonalDataExportGroupHtml.php b/tests/phpunit/tests/privacy/wpPrivacyGeneratePersonalDataExportGroupHtml.php
index 688f790e22..c98f94f87a 100644
|
a
|
b
|
class Tests_Privacy_WpPrivacyGeneratePersonalDataExportGroupHtml extends WP_Unit |
| 39 | 39 | ), |
| 40 | 40 | ); |
| 41 | 41 | |
| 42 | | $actual = wp_privacy_generate_personal_data_export_group_html( $data ); |
| | 42 | $actual = wp_privacy_generate_personal_data_export_group_html( $data, 'test-data-group' ); |
| 43 | 43 | $expected_table_markup = '<table><tbody><tr><th>Field 1 Name</th><td>Field 1 Value</td></tr><tr><th>Field 2 Name</th><td>Field 2 Value</td></tr></tbody></table>'; |
| 44 | 44 | |
| 45 | | $this->assertContains( '<h2>Test Data Group</h2>', $actual ); |
| | 45 | $this->assertContains( '<h2 id="test-data-group-test-data-group">Test Data Group</h2>', $actual ); |
| 46 | 46 | $this->assertContains( $expected_table_markup, $actual ); |
| 47 | 47 | } |
| 48 | 48 | |
| … |
… |
class Tests_Privacy_WpPrivacyGeneratePersonalDataExportGroupHtml extends WP_Unit |
| 79 | 79 | ), |
| 80 | 80 | ); |
| 81 | 81 | |
| 82 | | $actual = wp_privacy_generate_personal_data_export_group_html( $data ); |
| | 82 | $actual = wp_privacy_generate_personal_data_export_group_html( $data, 'test-data-group' ); |
| 83 | 83 | |
| 84 | | $this->assertContains( '<h2>Test Data Group', $actual ); |
| | 84 | $this->assertContains( '<h2 id="test-data-group-test-data-group">Test Data Group', $actual ); |
| 85 | 85 | $this->assertContains( '<td>Field 1 Value', $actual ); |
| 86 | 86 | $this->assertContains( '<td>Another Field 1 Value', $actual ); |
| 87 | 87 | $this->assertContains( '<td>Field 2 Value', $actual ); |
| … |
… |
class Tests_Privacy_WpPrivacyGeneratePersonalDataExportGroupHtml extends WP_Unit |
| 117 | 117 | ), |
| 118 | 118 | ); |
| 119 | 119 | |
| 120 | | $actual = wp_privacy_generate_personal_data_export_group_html( $data ); |
| | 120 | $actual = wp_privacy_generate_personal_data_export_group_html( $data, 'test-data-group' ); |
| 121 | 121 | |
| 122 | 122 | $this->assertContains( '<a href="http://wordpress.org">http://wordpress.org</a>', $actual ); |
| 123 | 123 | $this->assertContains( '<a href="https://wordpress.org">https://wordpress.org</a>', $actual ); |
| … |
… |
class Tests_Privacy_WpPrivacyGeneratePersonalDataExportGroupHtml extends WP_Unit |
| 131 | 131 | */ |
| 132 | 132 | public function test_group_labels_escaped() { |
| 133 | 133 | $data = array( |
| 134 | | 'group_label' => '<div>Escape HTML in group lavels</div>', |
| | 134 | 'group_label' => '<div>Escape HTML in group labels</div>', |
| 135 | 135 | 'items' => array(), |
| 136 | 136 | ); |
| 137 | 137 | |
| 138 | | $actual = wp_privacy_generate_personal_data_export_group_html( $data ); |
| | 138 | $actual = wp_privacy_generate_personal_data_export_group_html( $data, 'escape-html-in-group-labels' ); |
| 139 | 139 | |
| 140 | | $this->assertContains( '<h2><div>Escape HTML in group lavels</div></h2>', $actual ); |
| | 140 | $this->assertContains( '<h2 id="escape-html-in-group-labels-escape-html-in-group-labels"><div>Escape HTML in group labels</div></h2>', $actual ); |
| 141 | 141 | } |
| 142 | 142 | |
| 143 | 143 | /** |
| … |
… |
class Tests_Privacy_WpPrivacyGeneratePersonalDataExportGroupHtml extends WP_Unit |
| 162 | 162 | ), |
| 163 | 163 | ); |
| 164 | 164 | |
| 165 | | $actual = wp_privacy_generate_personal_data_export_group_html( $data ); |
| | 165 | $actual = wp_privacy_generate_personal_data_export_group_html( $data, 'test-data-group' ); |
| 166 | 166 | |
| 167 | 167 | $this->assertContains( $data['items'][0]['links']['value'], $actual ); |
| 168 | 168 | $this->assertContains( $data['items'][0]['formatting']['value'], $actual ); |
| … |
… |
class Tests_Privacy_WpPrivacyGeneratePersonalDataExportGroupHtml extends WP_Unit |
| 190 | 190 | ), |
| 191 | 191 | ); |
| 192 | 192 | |
| 193 | | $actual = wp_privacy_generate_personal_data_export_group_html( $data ); |
| | 193 | $actual = wp_privacy_generate_personal_data_export_group_html( $data, 'test-data-group' ); |
| 194 | 194 | |
| 195 | 195 | $this->assertNotContains( $data['items'][0]['scripts']['value'], $actual ); |
| 196 | 196 | $this->assertContains( '<td>Testing that script tags are stripped.</td>', $actual ); |
| … |
… |
class Tests_Privacy_WpPrivacyGeneratePersonalDataExportGroupHtml extends WP_Unit |
| 223 | 223 | ), |
| 224 | 224 | ); |
| 225 | 225 | |
| 226 | | $actual = wp_privacy_generate_personal_data_export_group_html( $data ); |
| | 226 | $actual = wp_privacy_generate_personal_data_export_group_html( $data, 'test-data-group' ); |
| 227 | 227 | |
| 228 | | $this->assertContains( '<h2>Test Data Group', $actual ); |
| | 228 | $this->assertContains( '<h2 id="test-data-group-test-data-group">Test Data Group', $actual ); |
| 229 | 229 | $this->assertContains( '<span class="count">(2)</span></h2>', $actual ); |
| 230 | 230 | $this->assertSame( 2, substr_count( $actual, '<table>' ) ); |
| 231 | 231 | } |
| … |
… |
class Tests_Privacy_WpPrivacyGeneratePersonalDataExportGroupHtml extends WP_Unit |
| 248 | 248 | ), |
| 249 | 249 | ); |
| 250 | 250 | |
| 251 | | $actual = wp_privacy_generate_personal_data_export_group_html( $data ); |
| | 251 | $actual = wp_privacy_generate_personal_data_export_group_html( $data, 'test-data-group' ); |
| 252 | 252 | |
| 253 | | $this->assertContains( '<h2>Test Data Group</h2>', $actual ); |
| | 253 | $this->assertContains( '<h2 id="test-data-group-test-data-group">Test Data Group</h2>', $actual ); |
| 254 | 254 | $this->assertNotContains( '<span class="count">', $actual ); |
| 255 | 255 | $this->assertSame( 1, substr_count( $actual, '<table>' ) ); |
| 256 | 256 | } |