Release - #2927
Conversation
feat: support XML and CSV exports for form submissions
Bundle Size Diff
|
There was a problem hiding this comment.
Pull request overview
Adds CSV export support for stored form submissions while preserving WordPress XML as the default.
Changes:
- Adds CSV generation and format selection.
- Introduces an accessible export-format dropdown.
- Expands unit and E2E export coverage.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
inc/plugins/class-form-records-export.php |
Generates XML or CSV exports. |
inc/plugins/class-dashboard.php |
Adds the export-format UI and download handling. |
tests/test-form-submissions.php |
Tests XML defaults and CSV output. |
src/blocks/test/e2e/blocks/form.spec.js |
Tests XML and CSV downloads. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if ( ! isset( $input_columns[ $label ] ) ) { | ||
| $input_columns[ $column_key ] = $label; | ||
| } |
| if ( 'file' === $input['type'] && isset( $input['metadata']['name'] ) ) { | ||
| $value = $input['metadata']['name']; | ||
| } | ||
|
|
||
| $row[ $column_key ] = $value; |
| item.addEventListener('click', () => { | ||
| runExport(item.dataset.format); | ||
| closeMenu(); | ||
| }); |
| $this->assertStringContainsString( 'Name', $output ); | ||
| $this->assertStringContainsString( 'Company', $output ); | ||
| $this->assertStringContainsString( 'Ada Lovelace', $output ); | ||
| $this->assertStringContainsString( 'Analytical Engines Ltd', $output ); |
|
Plugin build for d972bbb is ready 🛎️!
|
E2E TestsPlaywright Test Status: See serial and parallel matrix jobs Performance ResultsserverResponse: {"q25":365.9,"q50":388.95,"q75":402.7,"cnt":10}, firstPaint: {"q25":1515.3,"q50":1547.65,"q75":1731.9,"cnt":10}, domContentLoaded: {"q25":3703.2,"q50":3716.15,"q75":3771.7,"cnt":10}, loaded: {"q25":3705.1,"q50":3718.25,"q75":3774,"cnt":10}, firstContentfulPaint: {"q25":4185.1,"q50":4216.45,"q75":4274.8,"cnt":10}, firstBlock: {"q25":14806.1,"q50":14965,"q75":15176.7,"cnt":10}, type: {"q25":29.96,"q50":32.67,"q75":36.4,"cnt":10}, typeWithoutInspector: {"q25":28.54,"q50":30.03,"q75":31.99,"cnt":10}, typeWithTopToolbar: {"q25":37.39,"q50":38.83,"q75":41.02,"cnt":10}, typeContainer: {"q25":17.7,"q50":20.1,"q75":22.14,"cnt":10}, focus: {"q25":149.76,"q50":154.89,"q75":158.23,"cnt":10}, inserterOpen: {"q25":45.41,"q50":48.09,"q75":50.91,"cnt":10}, inserterSearch: {"q25":16.89,"q50":19.37,"q75":20.17,"cnt":10}, inserterHover: {"q25":7.02,"q50":7.65,"q75":8.21,"cnt":20}, loadPatterns: {"q25":1885.14,"q50":1935.61,"q75":2032.79,"cnt":10}, listViewOpen: {"q25":249.85,"q50":272.77,"q75":281.31,"cnt":10} |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (6)
inc/plugins/class-form-records-export.php:116
- This second
fputcsv()call also relies on the escape default deprecated in PHP 8.4, potentially emitting a deprecation into the download. Supply the escape parameter explicitly here as well.
$output->fputcsv( $line );
inc/plugins/class-dashboard.php:834
- After a keyboard user activates a format option,
closeMenu()hides the element that still owns focus, leaving focus inside hidden content. Move focus back to the toggle after closing the menu so keyboard and screen-reader navigation resumes at a visible control.
item.addEventListener('click', () => {
runExport(item.dataset.format);
closeMenu();
});
inc/plugins/class-dashboard.php:806
Response.text()decodes and consumes the UTF-8 BOM written by the CSV exporter, so rebuilding the download from that string drops the BOM and defeats the Excel encoding safeguard. Keep the response as bytes (for example, viaresponse.blob()) before assigning the CSV MIME type.
const isCsv = 'csv' === format;
const blob = new Blob([response], {type: isCsv ? 'text/csv;charset=utf-8' : 'text/xml'});
inc/plugins/class-form-records-export.php:284
- Truncating the post ID makes the exported
IDinaccurate once a site reaches IDs above eight digits and can create collisions between submissions. The record ID should be exported in full.
'id' => substr( strval( $record->ID ), -8 ),
inc/plugins/class-form-records-export.php:322
- This key collapses every input sharing a label. In particular, a multiple-file field stores one input per uploaded file with the same label (
src/blocks/frontend/form/index.js:103-118), so each assignment overwrites the previous filename and the CSV silently exports only the last file. Preserve repeated values by aggregating them or by using/disambiguating the stored input IDs.
$parsed[ 'input:' . $input['label'] ] = array(
'label' => $input['label'],
'value' => $value,
);
inc/plugins/class-form-records-export.php:102
- PHP 8.4 deprecates relying on
fputcsv()'s default escape parameter; with displayed deprecations this can also corrupt the generated CSV before its header. Pass an explicit empty escape string, which is supported by the project's PHP 7.4 minimum and produces standards-compliant CSV escaping.
This issue also appears on line 116 of the same file.
$output->fputcsv( array_map( array( $this, 'sanitize_cell' ), array_values( $columns ) ) );
Linked issues
This release will close the following issues once merged:
Public changelog