misc-scripts/events-csv.php
File Type: text/x-php
<?php
/**
* Plugin Name: CSV Exporter for Custom Post Type
* Plugin URI:
* Description: A WordPress plugin that adds a CSV download feature to the admin dashboard for exporting data from a custom post type, filtered by a date meta field (as timestamp), '_status' meta field, and optional taxonomy.
* Version: 1.0
* Author: Grok
* Author URI:
* License: GPL2
*/
/**
* Add admin menu page for the CSV exporter.
*/
function csv_exporter_admin_menu() {
add_menu_page(
'CSV Exporter', // Page title
'CSV Exporter', // Menu title
'manage_options', // Capability
'csv-exporter', // Menu slug
'csv_exporter_admin_page' // Callback function
);
}
add_action('admin_menu', 'csv_exporter_admin_menu');
/**
* Display the admin page with the form to download CSV.
*/
function csv_exporter_admin_page() {
?>
<div class="wrap">
<h1>CSV Exporter</h1>
<p>Enter the filters below and click "Download CSV" to export the data.</p>
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>">
<input type="hidden" name="action" value="download_csv">
<?php wp_nonce_field('download_csv', 'csv_exporter_nonce'); ?>
<label for="start">Start Date (YYYY-MM-DD):</label><br>
<input type="text" id="start" name="start" value="<?php echo esc_attr(date('Y-m-d', strtotime('-1 year'))); ?>" required pattern="\d{4}-\d{2}-\d{2}"><br><br>
<label for="end">End Date (YYYY-MM-DD):</label><br>
<input type="text" id="end" name="end" value="<?php echo esc_attr(date('Y-m-d')); ?>" required pattern="\d{4}-\d{2}-\d{2}"><br><br>
<label for="status">Status (comma-separated values, optional):</label><br>
<input type="text" id="status" name="status" value=""><br><br>
<input type="submit" class="button button-primary" value="Download CSV">
</form>
</div>
<?php
}
/**
* Handle the CSV download action.
*/
function csv_exporter_download_csv() {
// Check nonce and permissions
check_admin_referer('download_csv', 'csv_exporter_nonce');
if (!current_user_can('manage_options')) {
wp_die('You do not have sufficient permissions to access this page.');
}
// Customize these variables
$post_type = 'ajde_events'; // e.g., 'event'
$meta_key = 'evcal_srow'; // e.g., 'event_date'
$taxonomy = 'event_type'; // e.g., 'event_category' (set to empty string '' to disable taxonomy filter)
$terms = array('free-concert', 'cover-concert', 'benefit-concert', 'festival', 'festival-concert', 'pay-as-you-can-concert', 'ticketed-concert', 'off-site'); // Array of term slugs, or single string, or empty array [] to disable
// Fields to export: array of 'label' => 'post_field_or_meta_key'
// Use 'post_' prefix for core post fields, or just meta key for custom meta
$fields_to_export = array(
// 'ID' => 'post_ID',
'Title' => 'post_title',
// 'Publish Date' => 'post_date',
'Event Date' => $meta_key, // This will fetch the meta value (timestamp)
// 'Status' => '_status',
);
// Add taxonomy terms if taxonomy is set
if (!empty($taxonomy)) {
$fields_to_export['Event Type'] = $taxonomy;
}
// Get parameters from POST
$date_start = isset($_POST['start']) ? sanitize_text_field($_POST['start']) : date('Y-m-d', strtotime('-1 year'));
$date_end = isset($_POST['end']) ? sanitize_text_field($_POST['end']) : date('Y-m-d');
$status_input = isset($_POST['status']) ? sanitize_text_field($_POST['status']) : '';
// Validate date formats (YYYY-MM-DD)
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date_start) || !preg_match('/^\d{4}-\d{2}-\d{2}$/', $date_end)) {
wp_die('Invalid date format. Please use YYYY-MM-DD.');
}
// Convert to timestamps (start of day to end of day)
$date_start_ts = strtotime($date_start . ' 00:00:00');
$date_end_ts = strtotime($date_end . ' 23:59:59');
// Handle invalid dates from strtotime
if ($date_start_ts === false || $date_end_ts === false) {
wp_die('Invalid date values.');
}
// Ensure start <= end
if ($date_start_ts > $date_end_ts) {
// Swap if start > end
$temp = $date_start_ts;
$date_start_ts = $date_end_ts;
$date_end_ts = $temp;
}
// Get status values (comma-separated)
$status_values = !empty($status_input) ? array_filter(array_map('trim', explode(',', $status_input))) : array('scheduled');
// Build meta_query
$meta_query = array(
array(
'key' => $meta_key,
'value' => array($date_start_ts, $date_end_ts),
'compare' => 'BETWEEN',
'type' => 'NUMERIC'
)
);
if (!empty($status_values)) {
$meta_query[] = array(
'key' => '_status',
'value' => $status_values,
'compare' => 'IN'
);
}
if (count($meta_query) > 1) {
$meta_query['relation'] = 'AND';
}
// Query arguments
$args = array(
'post_type' => $post_type,
'post_status' => 'publish', // Or array('publish', 'draft') if needed
'posts_per_page' => -1, // Get all matching posts
'meta_query' => $meta_query,
'meta_key' => $meta_key, // Required for ordering by meta
'orderby' => 'meta_value_num',
'order' => 'ASC'
);
// Add tax_query if taxonomy and terms are set
if (!empty($taxonomy) && !empty($terms)) {
$args['tax_query'] = array(
array(
'taxonomy' => $taxonomy,
'field' => 'slug', // Change to 'term_id' if using IDs
'terms' => (array) $terms, // Ensure it's an array
'operator' => 'IN' // 'IN' for any of the terms, 'AND' for all, 'NOT IN' to exclude
)
);
}
// Run the query
$query = new WP_Query($args);
// Prepare CSV output
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=' . $post_type . '_export_' . date('Y-m-d') . '.csv');
// Open output stream
$output = fopen('php://output', 'w');
// Output headers
$headers = array_keys($fields_to_export);
fputcsv($output, $headers);
// Loop through posts
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
$row = array();
foreach ($fields_to_export as $label => $field) {
if (strpos($field, 'post_') === 0) {
// Core post field
$row[] = get_post_field($field, get_the_ID());
} elseif ($field === $taxonomy) {
// Taxonomy terms
$terms_list = wp_get_post_terms(get_the_ID(), $taxonomy, array('fields' => 'names'));
$row[] = implode(', ', $terms_list);
} else {
// Custom meta
if ($field == 'evcal_srow' || $field == 'evcal_erow')
$row[] = date('Y-m-d',get_post_meta(get_the_ID(), $field, true));
else
$row[] = get_post_meta(get_the_ID(), $field, true);
}
}
fputcsv($output, $row);
}
} else {
// No posts found, output a message row
fputcsv($output, array('No posts found matching the criteria.'));
}
// Close output
fclose($output);
// Reset query
wp_reset_postdata();
exit;
}
add_action('admin_post_download_csv', 'csv_exporter_download_csv');