Making WordPress.org

Changeset 2018


Ignore:
Timestamp:
10/29/2015 11:42:08 PM (10 years ago)
Author:
iandunn
Message:

WordCamp Payments Dashboard: Add support for exporting requests to a CSV.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/wordcamp.org/public_html/wp-content/plugins/wordcamp-payments-network/wordcamp-payments-network.php

    r1817 r2018  
    2525
    2626        add_action( 'wordcamp_payments_aggregate', array( __CLASS__, 'aggregate' ) );
     27        add_action( 'admin_enqueue_scripts',  array( __CLASS__, 'enqueue_assets' ) );
    2728        add_action( 'network_admin_menu', array( __CLASS__, 'network_admin_menu' ) );
    2829        add_action( 'init', array( __CLASS__, 'upgrade' ) );
     30        add_action( 'init', array( __CLASS__, 'process_export_request' ) );
    2931
    3032        // Diff-based updates to the index.
     
    127129            'post_id' => $request->ID,
    128130            'created' => get_post_time( 'U', true, $request->ID ),
     131                // todo Sometimes this is empty. Core normally catches this (r8636), but misses in our case because we don't use drafts. #1350-meta might have the side-effect of solving this.
     132            'paid'    => absint( get_post_meta( $request->ID, '_camppayments_date_vendor_paid', true ) ),
    129133            'due' => absint( get_post_meta( $request->ID, '_camppayments_due_by', true ) ),
    130134            'status' => $request->post_status,
     
    178182
    179183    /**
     184     * Enqueue scripts and stylesheets
     185     *
     186     * @param string $hook
     187     */
     188    public static function enqueue_assets( $hook ) {
     189        if ( 'index_page_wcp-dashboard' == $hook && 'export' == self::get_current_tab() ) {
     190            wp_enqueue_script( 'jquery-ui-datepicker' );
     191            wp_enqueue_style( 'jquery-ui' );
     192            wp_enqueue_style( 'wp-datepicker-skins' );
     193        }
     194    }
     195
     196    /**
    180197     * Renders the Dashboard - Payments screen.
    181198     */
    182199    public static function render_dashboard() {
    183200        ?>
     201
    184202        <div class="wrap">
    185             <?php screen_icon( 'tools' ); ?>
    186203            <h1>WordCamp Payments Dashboard</h1>
     204
    187205            <?php settings_errors(); ?>
     206
    188207            <h3 class="nav-tab-wrapper"><?php self::render_dashboard_tabs(); ?></h3>
    189208
    190             <?php self::$list_table->print_inline_css(); ?>
    191             <div id="wcp-list-table">
    192 
    193                 <?php self::$list_table->prepare_items(); ?>
    194                 <form id="posts-filter" action="" method="get">
    195                     <input type="hidden" name="page" value="wcp-dashboard" />
    196                     <input type="hidden" name="wcp-section" value="overdue" />
    197                     <?php self::$list_table->display(); ?>
    198                 </form>
    199 
    200             </div>
     209            <?php
     210                if ( 'export' == self::get_current_tab() ) {
     211                    self::render_export_tab();
     212                } else {
     213                    self::render_table_tabs();
     214                }
     215            ?>
     216
     217        </div> <!-- /wrap -->
     218
     219        <?php
     220    }
     221
     222    /**
     223     * Render the table tabs, like Overview, Pending, etc
     224     */
     225    protected static function render_table_tabs() {
     226        ?>
     227
     228        <?php self::$list_table->print_inline_css(); ?>
     229
     230        <div id="wcp-list-table">
     231            <?php self::$list_table->prepare_items(); ?>
     232
     233            <form id="posts-filter" action="" method="get">
     234                <input type="hidden" name="page" value="wcp-dashboard" />
     235                <input type="hidden" name="wcp-section" value="overdue" />
     236                <?php self::$list_table->display(); ?>
     237            </form>
     238        </div>
     239
     240        <?php
     241    }
     242
     243    /**
     244     * Process export requests
     245     */
     246    public static function process_export_request() {
     247        if ( empty( $_POST['submit'] ) || 'export' != self::get_current_tab() ) {
     248            return;
     249        }
     250
     251        if ( ! current_user_can( 'manage_network' ) || ! check_admin_referer( 'export', 'wcpn_request_export' ) ) {
     252            return;
     253        }
     254
     255        $start_date = strtotime( $_POST['wcpn_export_start_date'] . ' 00:00:00' );
     256        $end_date   = strtotime( $_POST['wcpn_export_end_date']   . ' 23:59:59' );
     257        $filename   = sanitize_file_name( sprintf( 'wordcamp-payments-%s-to-%s.csv', date( 'Y-m-d', $start_date ), date( 'Y-m-d', $end_date ) ) );
     258
     259        $report = self::generate_payment_report( $_POST['wcpn_date_type'], $start_date, $end_date );
     260
     261        if ( is_wp_error( $report ) ) {
     262            add_settings_error( 'wcp-dashboard', $report->get_error_code(), $report->get_error_message() );
     263        } else {
     264            header( 'Content-Type: text/csv' );
     265            header( sprintf( 'Content-Disposition: attachment; filename="%s"', $filename ) );
     266            header( 'Cache-control: private' );
     267            header( 'Pragma: private' );
     268            header( 'Expires: Mon, 26 Jul 1997 05:00:00 GMT' );
     269
     270            echo $report;
     271            die();
     272        }
     273    }
     274
     275    /*
     276     * Generate and return the raw payment report contents
     277     *
     278     * @param string $date_type 'paid' | 'created'
     279     * @param int $start_date
     280     * @param int $end_date
     281     *
     282     * @return string | WP_Error
     283     */
     284    protected static function generate_payment_report( $date_type, $start_date, $end_date ) {
     285        global $wpdb;
     286
     287        if ( ! in_array( $date_type, array( 'paid', 'created' ), true ) ) {
     288            return new WP_Error( 'wcpn_bad_date_type', 'Invalid date type.' );
     289        }
     290
     291        if ( ! is_int( $start_date ) || ! is_int( $end_date ) ) {
     292            return new WP_Error( 'wcpn_bad_dates', 'Invalid start or end date.' );
     293        }
     294
     295        $column_headings = array(
     296            'WordCamp', 'ID', 'Title', 'Status', 'Date Vendor was Paid', 'Creation Date', 'Due Date', 'Amount',
     297            'Currency', 'Category', 'Payment Method','Vendor Name', 'Vendor Contact Person', 'Vendor Country',
     298            'Check Payable To', 'URL', 'Supporting Documentation Notes',
     299        );
     300
     301        $table_name = self::get_table_name();
     302
     303        $request_indexes = $wpdb->get_results( $wpdb->prepare( "
     304            SELECT *
     305            FROM   `{$table_name}`
     306            WHERE  `{$date_type}` BETWEEN %d AND %d",
     307            $start_date,
     308            $end_date
     309        ) );
     310        $report = fopen( 'php://output', 'w' );
     311
     312        fputcsv( $report, $column_headings );
     313
     314        foreach( $request_indexes as $index ) {
     315            fputcsv( $report, self::get_report_row( $index ) );
     316        }
     317
     318        fclose( $report );
     319
     320        return ob_get_clean();
     321    }
     322
     323    /**
     324     * Gather all the request details needed for a row in the export file
     325     *
     326     * @param stdClass $index
     327     *
     328     * @return array
     329     */
     330    protected static function get_report_row( $index ) {
     331        switch_to_blog( $index->blog_id );
     332
     333        $request          = get_post( $index->post_id );
     334        $currency         = get_post_meta( $index->post_id, '_camppayments_currency',         true );
     335        $category         = get_post_meta( $index->post_id, '_camppayments_payment_category', true );
     336        $date_vendor_paid = get_post_meta( $index->post_id, '_camppayments_date_vendor_paid', true );
     337
     338        if ( $date_vendor_paid ) {
     339            $date_vendor_paid = date( 'Y-m-d', $date_vendor_paid );
     340        }
     341
     342        if ( 'null-select-one' === $currency ) {
     343            $currency = '';
     344        }
     345
     346        if ( 'null' === $category ) {
     347            $category = '';
     348        }
     349
     350        $row = array(
     351            get_wordcamp_name(),
     352            sprintf( '%d-%d', $index->blog_id, $index->post_id ),
     353            $request->post_title,
     354            $index->status,
     355            $date_vendor_paid,
     356            date( 'Y-m-d', $index->created ),
     357            date( 'Y-m-d', $index->due ),
     358            get_post_meta( $index->post_id, '_camppayments_payment_amount', true ),
     359            $currency,
     360            $category,
     361            get_post_meta( $index->post_id, '_camppayments_payment_method', true ),
     362            get_post_meta( $index->post_id, '_camppayments_vendor_name', true ),
     363            get_post_meta( $index->post_id, '_camppayments_vendor_contact_person', true ),
     364            get_post_meta( $index->post_id, '_camppayments_vendor_country', true ),
     365            get_post_meta( $index->post_id, '_camppayments_payable_to', true ),
     366            get_edit_post_link( $index->post_id ),
     367            get_post_meta( $index->post_id, '_camppayments_file_notes', true ),
     368        );
     369
     370        restore_current_blog();
     371
     372        return $row;
     373    }
     374
     375    /**
     376     * Render the Export tab
     377     */
     378    protected static function render_export_tab() {
     379        $today      = date( 'Y-m-d' );
     380        $last_month = date( 'Y-m-d', strtotime( 'now - 1 month' ) );
     381        ?>
     382
     383        <script>
     384            /**
     385             * Fallback to the jQueryUI datepicker if the browser doesn't support <input type="date">
     386             */
     387            jQuery( document ).ready( function( $ ) {
     388                var browserTest = document.createElement( 'input' );
     389                browserTest.setAttribute( 'type', 'date' );
     390
     391                if ( 'text' === browserTest.type ) {
     392                    $( '#wcpn_export' ).find( 'input[type=date]' ).datepicker( {
     393                        dateFormat : 'yy-mm-dd',
     394                        changeMonth: true,
     395                        changeYear : true
     396                    } );
     397                }
     398            } );
     399        </script>
     400
     401        <form id="wcpn_export" method="POST">
     402            <?php wp_nonce_field( 'export', 'wcpn_request_export' ); ?>
     403
     404            <p>
     405                This form will supply a CSV file with payment requests matching the parameters you select below.
     406                For example, all requests that were <code>paid</code> between <code><?php echo esc_html( $last_month ); ?></code> and <code><?php echo esc_html( $today ); ?></code>.
     407            </p>
     408
     409            <p>
     410                <label>
     411                    Date type:
     412                    <select name="wcpn_date_type">
     413                        <option value="created">created</option>
     414                        <option value="paid" selected>paid</option>
     415                    </select>
     416                </label>
     417            </p>
     418
     419            <p>
     420                <label>
     421                    Start date:
     422                    <input type="date" name="wcpn_export_start_date" class="medium-text" value="<?php echo esc_attr( $last_month ); ?>" />
     423                </label>
     424            </p>
     425
     426            <p>
     427                <label>
     428                    End date:
     429                    <input type="date" name="wcpn_export_end_date" class="medium-text" value="<?php echo esc_attr( $today ); ?>" />
     430                </label>
     431            </p>
     432
     433            <?php submit_button( 'Export' ); ?>
     434        </form>
     435
    201436        <?php
    202437    }
     
    217452        $tab = 'overdue';
    218453
    219         if ( isset( $_REQUEST['wcp-section'] ) && in_array( $_REQUEST['wcp-section'], array( 'pending', 'overdue', 'paid', 'incomplete' ) ) ) {
     454        if ( isset( $_REQUEST['wcp-section'] ) && in_array( $_REQUEST['wcp-section'], array( 'pending', 'overdue', 'paid', 'incomplete', 'export' ) ) ) {
    220455            $tab = $_REQUEST['wcp-section'];
    221456        }
     
    234469            'paid'    => 'Paid',
    235470            'incomplete' => __( 'Incomplete', 'wordcamporg' ),
     471            'export'     => __( 'Export', 'wordcamporg' ),
    236472        );
    237473
Note: See TracChangeset for help on using the changeset viewer.