obsolete.computer

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');

Meta