=' ) ) { add_action( 'bulk_actions-edit-shop_order', array( $this, 'bulk_actions' ), 20 ); } else { add_action( 'admin_footer', array( $this, 'bulk_actions_js' ) ); } add_filter( 'woocommerce_shop_order_search_fields', array( $this, 'search_fields' ) ); add_action( 'woocommerce_process_shop_order_meta', array( $this,'save_invoice_number_date' ), 35, 2 ); // manually send emails // WooCommerce core processes order actions at priority 50 add_action( 'woocommerce_process_shop_order_meta', array( $this, 'send_emails' ), 60, 2 ); add_action( 'admin_notices', array( $this, 'review_plugin_notice' ) ); add_action( 'admin_notices', array( $this, 'install_wizard_notice' ) ); add_action( 'init', array( $this, 'setup_wizard') ); // add_action( 'wpo_wcpdf_after_pdf', array( $this,'update_pdf_counter' ), 10, 2 ); add_action( 'admin_bar_menu', array( $this, 'debug_enabled_warning' ), 999 ); add_filter( 'manage_edit-shop_order_sortable_columns', array( $this, 'invoice_number_column_sortable' ) ); if ( defined( 'WC_VERSION' ) && version_compare( WC_VERSION, '3.0', '>=' ) ) { add_filter( 'request', array( $this, 'request_query_sort_by_invoice_number' ) ); } else { add_filter( 'pre_get_posts', array( $this, 'pre_get_posts_sort_by_invoice_number' ) ); } // AJAX actions for deleting and regenerating document data add_action( 'wp_ajax_wpo_wcpdf_delete_document', array( $this, 'delete_document' ) ); add_action( 'wp_ajax_wpo_wcpdf_regenerate_document', array( $this, 'regenerate_document' ) ); add_action( 'wpo_wcpdf_document_actions', array( $this, 'add_regenerate_document_button' ) ); add_action( 'wpo_wcpdf_document_actions', array( $this, 'add_document_action_feedback_icons' ) ); } // display review admin notice after 100 pdf downloads public function review_plugin_notice() { if ( $this->is_order_page() === false && !( isset( $_GET['page'] ) && $_GET['page'] == 'wpo_wcpdf_options_page' ) ) { return; } if ( get_option( 'wpo_wcpdf_review_notice_dismissed' ) !== false ) { return; } else { if ( isset( $_GET['wpo_wcpdf_dismis_review'] ) ) { update_option( 'wpo_wcpdf_review_notice_dismissed', true ); return; } // get invoice count to determine whether notice should be shown $invoice_count = $this->get_invoice_count(); if ( $invoice_count > 100 ) { // keep track of how many days this notice is show so we can remove it after 7 days $notice_shown_on = get_option( 'wpo_wcpdf_review_notice_shown', array() ); $today = date('Y-m-d'); if ( !in_array($today, $notice_shown_on) ) { $notice_shown_on[] = $today; update_option( 'wpo_wcpdf_review_notice_shown', $notice_shown_on ); } // count number of days review is shown, dismiss forever if shown more than 7 if (count($notice_shown_on) > 7) { update_option( 'wpo_wcpdf_review_notice_dismissed', true ); return; } $rounded_count = (int) substr( (string) $invoice_count, 0, 1 ) * pow( 10, strlen( (string) $invoice_count ) - 1); ?>

is_order_page() === false && !( isset( $_GET['page'] ) && $_GET['page'] == 'wpo_wcpdf_options_page' ) ) { return; } if ( get_option( 'wpo_wcpdf_install_notice_dismissed' ) !== false ) { return; } else { if ( isset( $_GET['wpo_wcpdf_dismis_install'] ) ) { update_option( 'wpo_wcpdf_install_notice_dismissed', true ); return; } if ( get_transient( 'wpo_wcpdf_new_install' ) !== false ) { ?>

plugin_path() . '/includes/class-wcpdf-setup-wizard.php' ); } } public function get_invoice_count() { global $wpdb; $invoice_count = $wpdb->get_var( $wpdb->prepare( "SELECT count(*) FROM {$wpdb->postmeta} WHERE meta_key = %s", '_wcpdf_invoice_number' ) ); return (int) $invoice_count; } public function update_pdf_counter( $document_type, $document ) { if ( in_array( $document_type, array('invoice','packing-slip') ) ) { $pdf_count = (int) get_option( 'wpo_wcpdf_count_'.$document_type, 0 ); update_option( 'wpo_wcpdf_count_'.$document_type, $pdf_count + 1 ); } } /** * Add PDF actions to the orders listing */ public function add_listing_actions( $order ) { // do not show buttons for trashed orders if ( $order->get_status() == 'trash' ) { return; } $this->disable_storing_document_settings(); $listing_actions = array(); $documents = WPO_WCPDF()->documents->get_documents(); foreach ($documents as $document) { $document_title = $document->get_title(); $icon = !empty($document->icon) ? $document->icon : WPO_WCPDF()->plugin_url() . "/assets/images/generic_document.png"; if ( $document = wcpdf_get_document( $document->get_type(), $order ) ) { $document_title = is_callable( array( $document, 'get_title' ) ) ? $document->get_title() : $document_title; $listing_actions[$document->get_type()] = array( 'url' => wp_nonce_url( admin_url( "admin-ajax.php?action=generate_wpo_wcpdf&document_type={$document->get_type()}&order_ids=" . WCX_Order::get_id( $order ) ), 'generate_wpo_wcpdf' ), 'img' => $icon, 'alt' => "PDF " . $document_title, 'exists' => is_callable( array( $document, 'exists' ) ) ? $document->exists() : false, ); } } $listing_actions = apply_filters( 'wpo_wcpdf_listing_actions', $listing_actions, $order ); foreach ($listing_actions as $action => $data) { ?>" target="_blank" alt="" data-tip=""> <?php echo $data['alt']; ?> get_settings(); if ( !isset( $invoice_settings['invoice_number_column'] ) ) { return $columns; } // put the column after the Status column $new_columns = array_slice($columns, 0, 2, true) + array( 'pdf_invoice_number' => __( 'Invoice Number', 'woocommerce-pdf-invoices-packing-slips' ) ) + array_slice($columns, 2, count($columns) - 1, true) ; return $new_columns; } /** * Display Invoice Number in Shop Order column (if available) * @param string $column column slug */ public function invoice_number_column_data( $column ) { global $post, $the_order; if ( $column == 'pdf_invoice_number' ) { $this->disable_storing_document_settings(); if ( empty( $the_order ) || WCX_Order::get_id( $the_order ) != $post->ID ) { $order = WCX::get_order( $post->ID ); if ( $invoice = wcpdf_get_invoice( $order ) ) { echo $invoice->get_number(); } do_action( 'wcpdf_invoice_number_column_end', $order ); } else { if ( $invoice = wcpdf_get_invoice( $the_order ) ) { echo $invoice->get_number(); } do_action( 'wcpdf_invoice_number_column_end', $the_order ); } } } /** * Add the meta box on the single order page */ public function add_meta_boxes() { // resend order emails if ( defined( 'WC_VERSION' ) && version_compare( WC_VERSION, '3.2', '>=' ) ) { add_meta_box( 'wpo_wcpdf_send_emails', __( 'Send order email', 'woocommerce-pdf-invoices-packing-slips' ), array( $this, 'send_order_email_meta_box' ), 'shop_order', 'side', 'high' ); } // create PDF buttons add_meta_box( 'wpo_wcpdf-box', __( 'Create PDF', 'woocommerce-pdf-invoices-packing-slips' ), array( $this, 'pdf_actions_meta_box' ), 'shop_order', 'side', 'default' ); // Invoice number & date add_meta_box( 'wpo_wcpdf-data-input-box', __( 'PDF document data', 'woocommerce-pdf-invoices-packing-slips' ), array( $this, 'data_input_box_content' ), 'shop_order', 'normal', 'default' ); } /** * Resend order emails */ public function send_order_email_meta_box( $post ) { global $theorder; // This is used by some callbacks attached to hooks such as woocommerce_resend_order_emails_available // which rely on the global to determine if emails should be displayed for certain orders. if ( ! is_object( $theorder ) ) { $theorder = wc_get_order( $post->ID ); } ?> disable_storing_document_settings(); $meta_box_actions = array(); $documents = WPO_WCPDF()->documents->get_documents(); $order = WCX::get_order( $post->ID ); foreach ($documents as $document) { $document_title = $document->get_title(); if ( $document = wcpdf_get_document( $document->get_type(), $order ) ) { $document_title = is_callable( array( $document, 'get_title' ) ) ? $document->get_title() : $document_title; $meta_box_actions[$document->get_type()] = array( 'url' => wp_nonce_url( admin_url( "admin-ajax.php?action=generate_wpo_wcpdf&document_type={$document->get_type()}&order_ids=" . $post_id ), 'generate_wpo_wcpdf' ), 'alt' => esc_attr( "PDF " . $document_title ), 'title' => "PDF " . $document_title, 'exists' => is_callable( array( $document, 'exists' ) ) ? $document->exists() : false, ); } } $meta_box_actions = apply_filters( 'wpo_wcpdf_meta_box_actions', $meta_box_actions, $post_id ); ?> ID ); $this->disable_storing_document_settings(); $invoice = wcpdf_get_document( 'invoice', $order ); do_action( 'wpo_wcpdf_meta_box_start', $order, $this ); if ( $invoice ) { // data $data = array( 'number' => array( 'label' => __( 'Invoice Number:', 'woocommerce-pdf-invoices-packing-slips' ), ), 'date' => array( 'label' => __( 'Invoice Date:', 'woocommerce-pdf-invoices-packing-slips' ), ), 'notes' => array( 'label' => __( 'Notes (printed in the invoice):', 'woocommerce-pdf-invoices-packing-slips' ), ), ); // output $this->output_number_date_edit_fields( $invoice, $data ); } do_action( 'wpo_wcpdf_meta_box_end', $order, $this ); } public function get_current_values_for_document( $document, $data ) { $current = array( 'number' => array( 'plain' => $document->exists() && ! empty( $document->get_number() ) ? $document->get_number()->get_plain() : '', 'formatted' => $document->exists() && ! empty( $document->get_number() ) ? $document->get_number()->get_formatted() : '', 'name' => "_wcpdf_{$document->slug}_number", ), 'date' => array( 'formatted' => $document->exists() && ! empty( $document->get_date() ) ? $document->get_date()->date_i18n( wc_date_format().' @ '.wc_time_format() ) : '', 'date' => $document->exists() && ! empty( $document->get_date() ) ? $document->get_date()->date_i18n( 'Y-m-d' ) : date_i18n( 'Y-m-d' ), 'hour' => $document->exists() && ! empty( $document->get_date() ) ? $document->get_date()->date_i18n( 'H' ) : date_i18n( 'H' ), 'minute' => $document->exists() && ! empty( $document->get_date() ) ? $document->get_date()->date_i18n( 'i' ) : date_i18n( 'i' ), 'name' => "_wcpdf_{$document->slug}_date", ), ); if ( !empty( $data['notes'] ) ) { $current['notes'] = array( 'value' => $document->get_document_notes(), 'name' =>"_wcpdf_{$document->slug}_notes", ); } foreach ( $data as $key => $value ) { if ( isset( $current[$key] ) ) { $data[$key] = array_merge( $current[$key], $value ); } } return apply_filters( 'wpo_wcpdf_current_values_for_document', $data, $document ); } public function output_number_date_edit_fields( $document, $data ) { if( empty( $document ) || empty( $data ) ) return; $data = $this->get_current_values_for_document( $document, $data ); ?>

get_title(); ?> exists() ) : ?> ">

exists() ) : ?>

order ); ?> get_title() ); ?>

()

@:

order ); ?>

order ); ?>
get_settings( true ); if ( $document->use_historical_settings() == true || isset( $document_settings['archive_pdf'] ) ) { printf( '', wp_create_nonce( "wpo_wcpdf_regenerate_document" ) ); } } public function add_document_action_feedback_icons( $document ) { echo ''; echo ''; } /** * Add actions to menu, WP3.5+ */ public function bulk_actions( $actions ) { foreach ($this->get_bulk_actions() as $action => $title) { $actions[$action] = $title; } return $actions; } /** * Add actions to menu, legacy method */ public function bulk_actions_js() { if ( $this->is_order_page() ) { ?> documents->get_documents(); foreach ($documents as $document) { $actions[$document->get_type()] = "PDF " . $document->get_title(); } return apply_filters( 'wpo_wcpdf_bulk_actions', $actions ); } /** * Save invoice number */ public function save_invoice_number_date($post_id, $post) { $post_type = get_post_type( $post_id ); if( $post_type == 'shop_order' ) { // bail if this is not an actual 'Save order' action if ( ! isset($_POST['action']) || $_POST['action'] != 'editpost' ) { return; } $order = WCX::get_order( $post_id ); if ( $invoice = wcpdf_get_invoice( $order ) ) { $document_data = $this->process_order_document_form_data( $_POST, $invoice->slug ); $invoice->set_data( $document_data, $order ); $invoice->save(); } // allow other documents to hook here and save their form data do_action( 'wpo_wcpdf_on_save_invoice_order_data', $_POST, $order, $this ); } } /** * Document objects are created in order to check for existence and retrieve data, * but we don't want to store the settings for uninitialized documents. * Only use in frontend/backed (page requests), otherwise settings will never be stored! */ public function disable_storing_document_settings() { add_filter( 'wpo_wcpdf_document_store_settings', array( $this, 'return_false' ), 9999 ); } public function restore_storing_document_settings() { remove_filter( 'wpo_wcpdf_document_store_settings', array( $this, 'return_false' ), 9999 ); } public function return_false(){ return false; } /** * Send emails manually */ public function send_emails( $post_id, $post ) { if ( ! empty( $_POST['wpo_wcpdf_send_emails'] ) ) { $order = wc_get_order( $post_id ); $action = wc_clean( $_POST['wpo_wcpdf_send_emails'] ); if ( strstr( $action, 'send_email_' ) ) { $email_to_send = str_replace( 'send_email_', '', $action ); // Switch back to the site locale. wc_switch_to_site_locale(); do_action( 'woocommerce_before_resend_order_emails', $order, $email_to_send ); // Ensure gateways are loaded in case they need to insert data into the emails. WC()->payment_gateways(); WC()->shipping(); // Load mailer. $mailer = WC()->mailer(); $mails = $mailer->get_emails(); if ( ! empty( $mails ) ) { foreach ( $mails as $mail ) { if ( $mail->id == $email_to_send ) { $mail->trigger( $order->get_id(), $order ); /* translators: %s: email title */ $order->add_order_note( sprintf( __( '%s email notification manually sent.', 'woocommerce-pdf-invoices-packing-slips' ), $mail->title ), false, true ); } } } do_action( 'woocommerce_after_resend_order_email', $order, $email_to_send ); // Restore user locale. wc_restore_locale(); // Change the post saved message. add_filter( 'redirect_post_location', function( $location ) { // messages in includes/admin/class-wc-admin-post-types.php // 11 => 'Order updated and sent.' return add_query_arg( 'message', 11, $location ); } ); } } } /** * Add invoice number to order search scope */ public function search_fields ( $custom_fields ) { $custom_fields[] = '_wcpdf_invoice_number'; $custom_fields[] = '_wcpdf_formatted_invoice_number'; return $custom_fields; } /** * Check if this is a shop_order page (edit or list) */ public function is_order_page() { global $post_type; if( $post_type == 'shop_order' ) { return true; } else { return false; } } /** * Add invoice number to order search scope */ public function invoice_number_column_sortable( $columns ) { $columns['pdf_invoice_number'] = 'pdf_invoice_number'; return $columns; } /** * Pre WC3.X sorting */ public function pre_get_posts_sort_by_invoice_number( $query ) { if( ! is_admin() ) { return; } $orderby = $query->get( 'orderby'); if( 'pdf_invoice_number' == $orderby ) { $query->set( 'meta_key', '_wcpdf_invoice_number' ); $query->set( 'orderby', apply_filters( 'wpo_wcpdf_invoice_number_column_orderby', 'meta_value' ) ); } } /** * WC3.X+ sorting */ public function request_query_sort_by_invoice_number( $query_vars ) { global $typenow; if ( in_array( $typenow, wc_get_order_types( 'order-meta-boxes' ), true ) ) { if ( isset( $query_vars['orderby'] ) ) { if ( 'pdf_invoice_number' === $query_vars['orderby'] ) { $query_vars = array_merge( $query_vars, array( 'meta_key' => '_wcpdf_invoice_number', 'orderby' => apply_filters( 'wpo_wcpdf_invoice_number_column_orderby', 'meta_value' ), ) ); } } } return $query_vars; } public function delete_document() { if ( check_ajax_referer( "wpo_wcpdf_delete_document", 'security', false ) === false ) { wp_send_json_error( array( 'message' => 'nonce expired', ) ); } if ( empty($_POST['order_id']) || empty($_POST['document']) ) { wp_send_json_error( array( 'message' => 'incomplete request', ) ); } if ( !current_user_can('manage_woocommerce') ) { wp_send_json_error( array( 'message' => 'no permissions', ) ); } $order_id = absint($_POST['order_id']); $document = sanitize_text_field($_POST['document']); try { $document = wcpdf_get_document( $document, wc_get_order( $order_id ) ); if ( !empty($document) && $document->exists() ) { $document->delete(); $response = array( 'message' => $document->get_type()." deleted", ); wp_send_json_success($response); } else { wp_send_json_error( array( 'message' => 'document does not exist', ) ); } } catch (\Exception $e) { wp_send_json_error( array( 'message' => 'error: '.$e->getMessage(), ) ); } } public function regenerate_document() { if ( check_ajax_referer( "wpo_wcpdf_regenerate_document", 'security', false ) === false ) { wp_send_json_error( array( 'message' => 'nonce expired', ) ); } if ( ! isset($_POST['action']) || $_POST['action'] != 'wpo_wcpdf_regenerate_document' ) { wp_send_json_error( array( 'message' => 'bad action', ) ); } if( empty($_POST['order_id']) || empty($_POST['document_type']) ) { wp_send_json_error( array( 'message' => 'incomplete request', ) ); } if ( !current_user_can('manage_woocommerce') ) { wp_send_json_error( array( 'message' => 'no permissions', ) ); } $order_id = absint( $_POST['order_id'] ); $order = WCX::get_order( $order_id ); $document_type = sanitize_text_field( $_POST['document_type'] ); // parse form data parse_str($_POST['form_data'], $form_data); if ( is_array( $form_data ) ) { foreach ( $form_data as $key => &$value ) { if ( is_array( $value ) && !empty( $value[$order_id] ) ) { $value = $value[$order_id]; } } } try { $document = wcpdf_get_document( $document_type, wc_get_order( $order_id ) ); if ( !empty($document) && $document->exists() ) { // perform legacy date fields replacements check if( isset( $form_data["_wcpdf_{$document->slug}_date"] ) && ! is_array( $form_data["_wcpdf_{$document->slug}_date"] ) ) { $form_data = $this->legacy_date_fields_replacements( $form_data, $document->slug ); } // save document data $document_data = $this->process_order_document_form_data( $form_data, $document->slug ); $document->regenerate( $order, $document_data ); $response = array( 'message' => $document->get_type()." regenerated", ); wp_send_json_success($response); } else { wp_send_json_error( array( 'message' => 'document does not exist', ) ); } } catch (\Exception $e) { wp_send_json_error( array( 'message' => 'error: '.$e->getMessage(), ) ); } } public function legacy_date_fields_replacements( $form_data, $document_slug ) { $legacy_date = sanitize_text_field( $form_data["_wcpdf_{$document_slug}_date"] ); $legacy_hour = sanitize_text_field( $form_data["_wcpdf_{$document_slug}_date_hour"] ); $legacy_minute = sanitize_text_field( $form_data["_wcpdf_{$document_slug}_date_minute"] ); unset( $form_data["_wcpdf_{$document_slug}_date_hour"] ); unset( $form_data["_wcpdf_{$document_slug}_date_minute"] ); $form_data["_wcpdf_{$document_slug}_date"] = array( 'date' => $legacy_date, 'hour' => $legacy_hour, 'minute' => $legacy_minute, ); return $form_data; } public function debug_enabled_warning( $wp_admin_bar ) { if ( isset(WPO_WCPDF()->settings->debug_settings['enable_debug']) && current_user_can( 'administrator' ) ) { $status_settings_url = 'admin.php?page=wpo_wcpdf_options_page&tab=debug'; $title = __( 'DEBUG output enabled', 'woocommerce-pdf-invoices-packing-slips' ); $args = array( 'id' => 'admin_bar_wpo_debug_mode', 'title' => sprintf( '%s', $status_settings_url, $title ), ); $wp_admin_bar->add_node( $args ); } } public function process_order_document_form_data( $form_data, $document_slug ) { $data = array(); if( isset( $form_data['_wcpdf_'.$document_slug.'_number'] ) ) { $data['number'] = sanitize_text_field( $form_data['_wcpdf_'.$document_slug.'_number'] ); } $date_entered = ! empty( $form_data['_wcpdf_'.$document_slug.'_date'] ) && ! empty( $form_data['_wcpdf_'.$document_slug.'_date']['date'] ); if( $date_entered ) { $date = $form_data['_wcpdf_'.$document_slug.'_date']['date']; $hour = ! empty( $form_data['_wcpdf_'.$document_slug.'_date']['hour'] ) ? $form_data['_wcpdf_'.$document_slug.'_date']['hour'] : '00'; $minute = ! empty( $form_data['_wcpdf_'.$document_slug.'_date']['minute'] ) ? $form_data['_wcpdf_'.$document_slug.'_date']['minute'] : '00'; // clean & sanitize input $date = date( 'Y-m-d', strtotime( $date ) ); $hour = sprintf('%02d', intval( $hour )); $minute = sprintf('%02d', intval( $minute ) ); $data['date'] = "{$date} {$hour}:{$minute}:00"; } elseif ( ! $date_entered && !empty( $_POST['_wcpdf_'.$document_slug.'_number'] ) ) { $data['date'] = current_time( 'timestamp', true ); } if ( isset( $form_data['_wcpdf_'.$document_slug.'_notes'] ) ) { // allowed HTML $allowed_html = array( 'a' => array( 'href' => array(), 'title' => array(), 'id' => array(), 'class' => array(), 'style' => array(), ), 'br' => array(), 'em' => array(), 'strong'=> array(), 'div' => array( 'id' => array(), 'class' => array(), 'style' => array(), ), 'span' => array( 'id' => array(), 'class' => array(), 'style' => array(), ), 'p' => array( 'id' => array(), 'class' => array(), 'style' => array(), ), 'b' => array(), ); // sanitize $notes = sanitize_textarea_field( wp_kses( $form_data['_wcpdf_'.$document_slug.'_notes'], $allowed_html ) ); $data['notes'] = nl2br( $notes ); } return $data; } } endif; // class_exists return new Admin();