Code Lover
Code Lover

Reputation: 8348

Generate multiple pages pdf in PHP Loop via AJAX using mPDF library

I am developing a plugin that generates various PDFs using AJAX. I have done all but stuck on generating multiple PDFs for each user using the loop.

I prefer to generate PDF with multiple pages for each user. However, if not possible, then a separate PDF for each user would work as well.

The below code is generating only one page for probably for the first user in the loop. Then generate one blank page and stop the iteration.

Please see mPDF Library

Data

Array
(
    [group_name] => Food Lovers
    [group_admin] => John Doe
    [identifier] => AtR4deAVgU4Ensi1_1ac2b33a4df7c5f0cf148d6232074352
    [group_order_number] => 1615962332298
    [start_date] => 2021-03-20
    [group_user_ids] => Array
        (
            [0] => 63
            [1] => 73
            [2] => 83
        )

    [63] => Array
        (
            [products] => Array
                (
                    [0] => stdClass Object
                        (
                            [id] => 100
                            [order_number] => 2021031729863
                            [group_order_number] => 1615962332298
                            [product] => 100
                            [product_option] => 
                            [qty] => 6
                            [group_id] => 298
                            [group_admin] => 72
                            [group_user] => 63
                            [identifier] => AtR4deAVgU4Ensi1_1ac2b33a4df7c5f0cf148d6232074352
                            [added_at] => 2021-03-17 10:25:32
                            [price] => 428
                            [total] => 2568
                            [product_name] => Ea ad doloribus consequuntur et qui nihil
                            [customers] => Array
                                (
                                    [Subotdh [email protected]] => Array
                                        (
                                            [name] => Subotdh Ringo
                                            [email] => [email protected]
                                            [qty] => 2
                                            [total_qty] => 8
                                        )

                                    [[email protected]] => Array
                                        (
                                            [name] => Chintamani
                                            [email] => [email protected]
                                            [qty] => 4
                                            [total_qty] => 17
                                        )

                                )

                        )

                    ...

                )

            [product_groups] => Array
                (
                    [0] => stdClass Object
                        (
                            [id] => 2
                            [order_number] => 2021031729863
                            [group_order_number] => 1615962332298
                            [product_group] => 40
                            [qty] => 6
                            [group_id] => 298
                            [group_admin] => 72
                            [group_user] => 63
                            [customers] => Array
                                (
                                    [0] => stdClass Object
                                        (
                                            [name] => Subotdh Ringo
                                            [email] => [email protected]
                                            [qty] => 2
                                            [discount] => 316
                                        )

                                    [1] => stdClass Object
                                        (
                                            [name] => Chintamani
                                            [email] => [email protected]
                                            [qty] => 4
                                            [discount] => 632
                                        )

                                )

                            [identifier] => AtR4deAVgU4Ensi1_1ac2b33a4df7c5f0cf148d6232074352
                            [added_at] => 2021-03-17 10:25:32
                            [price] => 1621
                            [discount] => 158
                            [discounted_price] => 1463
                            [total] => 8778
                            [product_count] => 4
                            [product_group_name] => Quibusdam unde
                        )

                    ...

                )

            [pg_discount] => Array
                (
                    [Subotdh [email protected]] => Array
                        (
                            [name] => Subotdh Ringo
                            [email] => [email protected]
                            [total_qty] => 2
                            [total_discount] => 316
                        )

                    [[email protected]] => Array
                        (
                            [name] => Chintamani
                            [email] => [email protected]
                            [total_qty] => 4
                            [total_discount] => 632
                        )

                    [Dingon [email protected]] => Array
                        (
                            [name] => Dingon Dksi
                            [email] => [email protected]
                            [total_qty] => 1
                            [total_discount] => 150
                        )

                )

        )

        ...
)

Callback Function

function gs_group_users_order_pdf_generator_ajax()
{
    // Check if user is logged in
    if ( ! is_user_logged_in()) {
        // throw error if user is not logged in
        wp_send_json_error(__('Please login to order', 'group-shop'));

        // we use this manually as want to print error
        wp_die();
    }

    // Check if user is logged in
    if ( ! current_user_can('administrator')) {
        // throw error if user is not logged in
        wp_send_json_error(__('You are not authorized to perform this action', 'group-shop'));

        // we use this manually as want to print error
        wp_die();
    }

    // check and validate nonce
    if ( ! check_ajax_referer('gs_nonce', 'nonce', FALSE)) {

        // throw error if validation fails
        wp_send_json_error(__('Do not be nasty with validation', 'group-shop'));

        // we use this manually as want to print error
        wp_die();
    }

    $action             = $_POST[ 'action' ];
    $nonce              = $_POST[ 'nonce' ];
    $group_order_number = $_POST[ 'group_order_number' ];
    $group_id           = $_POST[ 'group_id' ];
    $group_admin_id     = $_POST[ 'group_admin' ];
    $identifier         = $_POST[ 'identifier' ];
    $status             = $_POST[ 'status' ];
    $group              = get_the_title($group_id);
    $group_admin        = get_userdata($group_admin_id);

    $order          = new Group_Shop_Order();
    $data           = $order->prepare_group_users_orders_pdf_data($group_order_number, $group_id, $group_admin_id, $identifier);
    $group_user_ids = $data[ 'group_user_ids' ];
    $filename       = $group_order_number . '.pdf';

    ob_clean();

    // init mpdf
    try {
        $mpdf = new Mpdf([
            'default_font_size' => 6,
            'default_font'      => 'Helvetica',
            'orientation'       => 'L',
        ]);

        // write pdf
        $stylesheet                 = file_get_contents(GROUP_SHOP_ROOT . 'public/css/invoice.css');
        $mpdf->shrink_tables_to_fit = 1;
        $mpdf->WriteHTML($stylesheet, HTMLParserMode::HEADER_CSS);

        foreach ($group_user_ids as $group_user_id) :

            $user_data = get_userdata($group_user_id);

            header('Content-type: application/pdf');
            header('Content-Disposition: inline; filename="' . $filename . '"');
            header('Content-Transfer-Encoding: binary');
            header('Accept-Ranges: bytes');

            // create pdf
            $markup = '<div class="info">';
            $markup .= '<p><strong>' . __('User', 'group-shop') . ':</strong> ' . $user_data->display_name . '</p>';
            $markup .= '<p><strong>Email:</strong> ' . $user_data->user_email . '</p>';
            $markup .= '<p><strong>Admin:</strong> ' . $data[ 'group_admin' ] . '</p>';
            $markup .= '<p><strong>Group:</strong> ' . $data[ 'group_name' ] . '</p>';
            $markup .= '</div>';

            $markup .= '<table class="table">';
                // table markup
            $markup .= '</table>';

            // end of order table

            $markup .= '<pagebreak />';  //page break

        endforeach; // $group_user_ids end

        $mpdf->WriteHTML($markup, HTMLParserMode::HTML_BODY, TRUE);

        // create directory if not exists
        $orders_dirname  = 'tvm-orders' . DIRECTORY_SEPARATOR . 'user-orders';
        $orders_root_dir = WP_CONTENT_DIR . DIRECTORY_SEPARATOR . $orders_dirname;
        $orders_pdf_dir  = $orders_root_dir . DIRECTORY_SEPARATOR . $group_order_number;
        $order_pdf_url   = content_url($orders_dirname . '/' . $group_order_number . '/' . $filename);
        $success_message = __('Group User Orders PDF is generated and opened in another tab.', 'group-shop');

        // check if pdf is exists, just open it
        // @todo uncomment in production
    //        if (file_exists($orders_pdf_dir . DIRECTORY_SEPARATOR . $filename)) {
    //
    //            wp_send_json_success([
    //                'message'      => $success_message,
    //                'redirect_url' => $order_pdf_url,
    //            ], 200);
    //        }

        // create directory
        if ( ! is_dir($orders_pdf_dir)) {
            // create directories
            wp_mkdir_p($orders_pdf_dir);
            // create index.php file for root and sub-folders
            gs_create_file_recursively($orders_root_dir, 'index.php');
        }

        // save pdf file
        $mpdf->Output($orders_pdf_dir . DIRECTORY_SEPARATOR . $filename, 'F');

        // show success message once record updated
        wp_send_json_success([
            'message'       => $success_message,
            'generated_url' => $order_pdf_url,
        ], 200);

    } catch
    (MpdfException $e) {
        // throw error if fails to insert record
        wp_send_json_error(__('Something went wrong', 'group-shop'));
    }

    ob_end_flush();

}

// hook the function
add_action('wp_ajax_gs_group_users_order_pdf_generator', 'gs_group_users_order_pdf_generator_ajax');
add_action('wp_ajax_nopriv_gs_group_users_order_pdf_generator', 'gs_group_users_order_pdf_generator_ajax');

Javascript

Calling function

// to generate group user orders pdfs
$(document).on('click', '.gs-guo-pdf-orders', function () {
    if (confirm('Are you sure you want to generate group users order PDFs?')) {
        // process ajax data
        ajax_process.call(this, '', 'gs_group_users_order_pdf_generator', 'fa-window-close');
    }
});

Compelete Javascript

(function ($) {
    $(function () {

        let response_alert = $('#response');
        response_alert.hide();

        /**
         * process ajax data
         *
         * @param {string} status - Order status. Available options are P, C, D
         * @param icon
         * @param action
         * @returns void
         */
        function ajax_process(status, action, icon) {
            // process data
            let data_order_num = $(this).data('ordernum');
            let data_gid = $(this).data('gid');
            let data_gadmin = $(this).data('gadmin');
            let data_identifier = $(this).data('identifier');

            // button feedback and disable
            $(this).find('i').removeClass(icon).addClass('fa-sync-alt');
            $(this).addClass('updating').prop('disabled', true);

            $.ajax({
                method: 'POST',
                dataType: 'json',
                context: this,
                url: ajax_vars.ajax_url,
                data: {
                    action: action,
                    nonce: ajax_vars.nonce,
                    group_order_number: data_order_num,
                    group_id: data_gid,
                    group_admin: data_gadmin,
                    identifier: data_identifier,
                    status: status,
                },
                success: function (response) {

                    if (response.success === true) {
                        // get the response message
                        let message = response.data.message;

                        // display success message
                        response_alert.fadeIn().prepend(alerts('success', message));

                        // redirect if already exists
                        if (response.data.redirect_url !== undefined) {
                            // window.location.href = response.data.redirect_url;
                            window.open(
                                response.data.redirect_url,
                                '_blank'
                            )
                        }

                        // redirect if newly generated
                        if (response.data.generated_url !== undefined) {
                            // window.location.href = response.data.redirect_url;
                            window.open(
                                response.data.generated_url,
                                '_blank'
                            )
                        }

                    }

                    if (response.success === false) {
                        response_alert.fadeIn().prepend(alerts('error', response.data));
                    }
                    gs_alert_stats();

                    // update datatables data
                    $('#gsAllOrdersTable').DataTable().ajax.reload();
                },
                error: function (response) {
                    let error_message = (response.data === undefined) ? 'Something went wrong!' : response.data;
                    response_alert.fadeIn().prepend(alerts('error', error_message));
                    gs_alert_stats();
                },
                complete: function () {

                    $(this).find('i').removeClass('fa-sync-alt').addClass('fa-check');
                    $(this).removeClass('updating').prop('disabled', false);
                }
            });
        }

        // to deliver
        $(document).on('click', '.gs-deliver-order', function () {
            if (confirm('Are you sure you want to change status to Deliver?')) {
                //process ajax data
                ajax_process.call(this, 'D', 'gs_status_group_order_item', 'fa-shipping-fast');
            }
        });

        // to pending
        $(document).on('click', '.gs-pending-order', function () {
            if (confirm('Are you sure you want to change status to Pending?')) {
                //process ajax data
                ajax_process.call(this, 'P', 'gs_status_group_order_item', 'fa-exclamation-triangle');
            }
        });

        // to cancel
        $(document).on('click', '.gs-cancel-order', function () {
            if (confirm('Are you sure you want to change status to Cancel?')) {
                // process ajax data
                ajax_process.call(this, 'C', 'gs_status_group_order_item', 'fa-window-close');
            }
        });

        // to generate group order pdf
        $(document).on('click', '.gs-go-pdf-order', function () {
            if (confirm('Are you sure you want to generate a group order PDF?')) {
                // process ajax data
                ajax_process.call(this, '', 'gs_group_order_pdf_generator', 'fa-window-close');
            }
        });

        // to generate group user orders pdfs
        $(document).on('click', '.gs-guo-pdf-orders', function () {
            if (confirm('Are you sure you want to generate group users order PDFs?')) {
                // process ajax data
                ajax_process.call(this, '', 'gs_group_users_order_pdf_generator', 'fa-window-close');
            }
        });

        /**
         * response alert
         */
        function gs_alert_stats() {
            let gs_alert = $('.gs-message');
            $('.gs-close').on('click', function () {
                alerts('Clicked');
                $(this).parent(gs_alert).fadeOut();
            });
        }


    });
})(jQuery);

HTML for Button

<button class="gs-guo-pdf-orders btn btn-sm btn-outline-info ml-3" type="button" title="Generate Group Users Order PDFs" 
data-ordernum="1615962332298" data-gid="298" data-gadmin="72" data-identifier="AtR4deAVgU4Ensi1_1ac2b33a4df7c5f0cf148d6232074352">
<i class="fas fa-copy"></i></button>

Upvotes: 1

Views: 1371

Answers (1)

Jalzhar
Jalzhar

Reputation: 36

I'm not sure if this is the problem. But you are rewriting $markup variable every loop in the foreach with this sentence:

$markup = '<div class="info">';

You must to define $markup as empty before the foreach and then concatenate strings inside the foreach

$markup = ''; //<-- Add this first

// Headers are better out of the loop
header('Content-type: application/pdf');
header('Content-Disposition: inline; filename="' . $filename . '"');
header('Content-Transfer-Encoding: binary');
header('Accept-Ranges: bytes');
foreach ($group_user_ids as $group_user_id) {

    $user_data = get_userdata($group_user_id);

    // create pdf
    $markup .= '<div class="info">'; //<-- Concat here, you are rewriting
    $markup .= '<p><strong>' . __('User', 'group-shop') . ':</strong> ' . $user_data->display_name . '</p>';
    $markup .= '<p><strong>Email:</strong> ' . $user_data->user_email . '</p>';
    $markup .= '<p><strong>Admin:</strong> ' . $data[ 'group_admin' ] . '</p>';
    $markup .= '<p><strong>Group:</strong> ' . $data[ 'group_name' ] . '</p>';
    $markup .= '</div>';

    $markup .= '<table class="table">';
        // table markup
    $markup .= '</table>';

    // end of order table

    $markup .= '<pagebreak />';  //page break

} // $group_user_ids end
$mpdf->WriteHTML($markup, HTMLParserMode::HTML_BODY, TRUE);

Upvotes: 1

Related Questions