<?php
// Add an "Export CSV" button above the listing template that exports selected post data of posts in the filtered results
// Part 1 - Add the "Export CSV" button above the listing
add_action( 'facetwp_scripts', function() {
?>
<script>
var fwp_export = {
nonce: '<?php echo wp_create_nonce('fwp_export_csv'); ?>',
ajaxurl: '<?php echo admin_url('admin-ajax.php'); ?>'
};
</script>
<script>
(function() {
document.addEventListener('facetwp-loaded', function() {
// Only inject the button once
if (!document.querySelector('.fwp-export-btn')) {
var btn = document.createElement('button');
btn.className = 'fwp-export-btn';
btn.textContent = 'Export CSV';
document.querySelector('.facetwp-template').insertAdjacentElement('beforebegin', btn);
btn.addEventListener('click', function() {
var params = new URLSearchParams();
params.set('action', 'fwp_export_csv');
params.set('nonce', fwp_export.nonce);
window.location.href = fwp_export.ajaxurl + '?' + params.toString();
});
}
});
})();
</script>
<?php
}, 100 );
// Part 2 - Store filtered post IDs in a transient
add_filter( 'facetwp_filtered_post_ids', function( $post_ids, $class ) {
// Only store the transient on the relevant listing.
// Use $class->ajax_params['template'] to check for a FacetWP listing.
// Or use $class->http_params['uri'] to check the URI if it is another listing template type
// For examples, see: https://facetwp.com/help-center/developers/hooks/querying-hooks/facetwp_filtered_post_ids/#usage-examples
if ( 'my_template' !== $class->ajax_params['template'] ) { // Change "my_template" to the name of your template
return $post_ids;
}
$session_id = fwp_get_export_session_id();
if ( empty( $session_id ) ) {
return $post_ids;
}
set_transient( 'fwp_export_ids_' . $session_id, $post_ids, 5 * MINUTE_IN_SECONDS );
return $post_ids;
}, 10, 2 );
// Part 3 - Set cookie instead of session ID for logged-out users
// Remove this part if the button is admin-only
add_action( 'init', function() {
if ( ! is_user_logged_in() && empty( $_COOKIE['fwp_export_session'] ) ) {
$token = wp_generate_password( 12, false );
setcookie( 'fwp_export_session', $token, time() + 3600, COOKIEPATH, COOKIE_DOMAIN );
$_COOKIE['fwp_export_session'] = $token; // make it available in the same request
}
} );
// Part 4 - Get a session ID from the transient (when logged in) or cookie (when logged out)
function fwp_get_export_session_id() {
$token = wp_get_session_token();
if ( ! empty( $token ) ) {
return $token;
}
// Cookie fallback for logged-out users
// Remove these lines if the button is admin-only
return ! empty( $_COOKIE['fwp_export_session'] )
? sanitize_key( $_COOKIE['fwp_export_session'] )
: '';
}
// Part 5 - Handle CSV export
add_action( 'wp_ajax_fwp_export_csv', 'fwp_handle_export_csv' );
add_action( 'wp_ajax_nopriv_fwp_export_csv', 'fwp_handle_export_csv' ); // Only for logged-out users. Remove if the button is admin-only.
function fwp_handle_export_csv() {
ob_start(); // Catch any accidental output
check_ajax_referer( 'fwp_export_csv', 'nonce' );
$session_id = fwp_get_export_session_id();
if ( empty( $session_id ) ) {
wp_die( 'Session not found.' );
}
$post_ids = get_transient( 'fwp_export_ids_' . $session_id );
if ( empty( $post_ids ) ) {
wp_die( 'No results to export.' );
}
$query = new WP_Query( [
'post__in' => $post_ids,
'orderby' => 'post__in',
'posts_per_page' => -1,
'post_type' => 'any',
] );
ob_end_clean(); // Discard any buffered output before sending headers
header( 'Content-Type: text/csv; charset=utf-8' );
header( 'Content-Disposition: attachment; filename="export.csv"' );
$out = fopen( 'php://output', 'w' );
if ( ! $out ) {
wp_die( 'Could not open output stream.' );
}
fputcsv( $out, [ 'Post ID', 'Post Title', 'Post Date', 'My field' ] ); // Add CSV headings for the output below
foreach ( $query->posts as $post ) {
fputcsv( $out, [
$post->ID,
$post->post_title,
$post->post_date,
get_field( 'my_field_name', $post->ID ),// example ACF field
//.. add any other data
] );
}
fclose( $out );
exit;
}