Files
old-experiments/backend/wordpress/wp-content/plugins/woocommerce-jetpack/includes/class-wcj-pdf-invoicing.php
2018-06-29 14:40:28 +02:00

476 lines
16 KiB
PHP
Executable File

<?php
/**
* Booster for WooCommerce - Module - PDF Invoicing
*
* @version 3.5.2
* @author Algoritmika Ltd.
*/
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
if ( ! class_exists( 'WCJ_PDF_Invoicing' ) ) :
class WCJ_PDF_Invoicing extends WCJ_Module {
/**
* Constructor.
*
* @version 3.5.0
*/
function __construct() {
$this->id = 'pdf_invoicing';
$this->short_desc = __( 'PDF Invoicing', 'woocommerce-jetpack' );
$this->section_title = __( 'General', 'woocommerce-jetpack' );
$this->desc = __( 'Invoices, Proforma Invoices, Credit Notes and Packing Slips.', 'woocommerce-jetpack' );
$this->link_slug = 'woocommerce-pdf-invoicing-and-packing-slips';
parent::__construct();
$this->add_tools( array(
'renumerate_invoices' => array(
'title' => __( 'Invoices Renumerate', 'woocommerce-jetpack' ),
'desc' => __( 'Tool renumerates all invoices, proforma invoices, credit notes and packing slips.', 'woocommerce-jetpack' ),
),
'invoices_report' => array(
'title' => __( 'Invoices Report', 'woocommerce-jetpack' ),
'desc' => __( 'Invoices Monthly Reports.', 'woocommerce-jetpack' ),
),
) );
if ( $this->is_enabled() ) {
add_action( 'init', array( $this, 'catch_args' ) );
add_action( 'init', array( $this, 'generate_pdf_on_init' ) );
// Bulk actions
add_action( 'admin_footer-edit.php', array( $this, 'bulk_actions_pdfs_admin_footer' ) );
add_action( 'load-edit.php', array( $this, 'bulk_actions_pdfs' ) );
add_action( 'admin_notices', array( $this, 'bulk_actions_pdfs_notices' ) );
$this->the_pdf_invoicing_report_tool = include_once( 'pdf-invoices/class-wcj-pdf-invoicing-report-tool.php' );
$invoice_types = wcj_get_enabled_invoice_types();
foreach ( $invoice_types as $invoice_type ) {
$the_hooks = wcj_get_invoice_create_on( $invoice_type['id'] );
foreach ( $the_hooks as $the_hook ) {
if ( 'manual' != $the_hook ) {
add_action( $the_hook, array( $this, 'create_document_hook' ) );
if ( 'woocommerce_new_order' === $the_hook ) {
add_action( 'woocommerce_api_create_order', array( $this, 'create_document_hook' ) );
add_action( 'woocommerce_cli_create_order', array( $this, 'create_document_hook' ) );
add_action( 'kco_before_confirm_order', array( $this, 'create_document_hook' ) );
add_action( 'woocommerce_checkout_order_processed', array( $this, 'create_document_hook' ) );
}
}
}
}
// Editable numbers in meta box
if ( 'yes' === get_option( 'wcj_invoicing_add_order_meta_box_numbering', 'yes' ) ) {
add_action( 'save_post_shop_order', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
}
}
}
/**
* Add extra bulk action options to generate/download documents.
*
* Using Javascript until WordPress core fixes: http://core.trac.wordpress.org/ticket/16031
*
* @see https://www.skyverge.com/blog/add-custom-bulk-action/
* @version 3.5.0
* @since 2.5.7
* @todo add bulk actions in a correct way for newer WP
*/
function bulk_actions_pdfs_admin_footer() {
global $post_type;
if ( 'shop_order' == $post_type ) {
$invoice_types = wcj_get_enabled_invoice_types();
$actions = array(
'generate' => __( 'Generate', 'woocommerce-jetpack' ),
'download' => __( 'Download (Zip)', 'woocommerce-jetpack' ),
'merge' => __( 'Merge (Print)', 'woocommerce-jetpack' ),
);
$html = '';
$html .= '<script type="text/javascript">';
foreach ( $actions as $action_id => $action_title ) {
foreach ( $invoice_types as $invoice_type ) {
$key = $invoice_type['id'];
$title = $invoice_type['title'];
$html .= 'jQuery(function() { ';
foreach ( array( 'action', 'action2' ) as $action ) {
$html .= 'jQuery(\'<option>\').' .
'val(\''. $action_id . '_' . $key . '\').' .
'text(\'' . $action_title . ' ' . $title . '\').' .
'appendTo(\'select[name="' . $action . '"]\'); ';
}
$html .= '}); ';
}
}
$html .= '</script>';
echo $html;
}
}
/**
* bulk_actions_pdfs_notices.
*
* @version 3.5.2
* @since 2.5.7
*/
function bulk_actions_pdfs_notices() {
global $post_type, $pagenow;
if ( $pagenow == 'edit.php' && 'shop_order' == $post_type ) {
if ( isset( $_REQUEST['generated'] ) && (int) $_REQUEST['generated'] ) {
$message = sprintf( _n( 'Document generated.', '%s documents generated.', $_REQUEST['generated'] ), number_format_i18n( $_REQUEST['generated'] ) );
echo "<div class='updated'><p>{$message}</p></div>";
}
if ( isset( $_GET['wcj_notice'] ) ) {
switch ( $_GET['wcj_notice'] ) {
case 'ziparchive_class_missing':
echo '<div class="notice notice-error"><p><strong>' .
sprintf( __( 'Booster: %s class is not accessible on your server. Please contact your hosting provider.', 'woocommerce-jetpack' ),
'<a target="_blank" href="http://php.net/manual/en/class.ziparchive.php">PHP ZipArchive</a>' ) .
'</strong></p></div>';
break;
case 'ziparchive_error':
echo '<div class="notice notice-error"><p>' .
__( 'Booster: ZipArchive error.', 'woocommerce-jetpack' ) .
'</p></div>';
break;
case 'merge_pdfs_no_files':
echo '<div class="notice notice-error"><p>' .
__( 'Booster: Merge PDFs: No files.', 'woocommerce-jetpack' ) .
'</p></div>';
break;
case 'merge_pdfs_php_version':
echo '<div class="notice notice-error"><p>' .
sprintf( __( 'Booster: Merge PDFs: Command requires PHP version 5.3.0 at least. You have PHP version %s installed.', 'woocommerce-jetpack' ), PHP_VERSION ) .
'</p></div>';
break;
default:
echo '<div class="notice notice-error"><p>' .
sprintf( __( 'Booster: %s.', 'woocommerce-jetpack' ), '<code>' . $_GET['wcj_notice'] . '</code>' ) .
'</p></div>';
break;
}
}
}
}
/**
* bulk_actions_pdfs.
*
* @version 3.5.0
* @since 2.5.7
* @todo on `generate` (and maybe other actions) validate user permissions/capabilities - `if ( ! current_user_can( $post_type_object->cap->export_post, $post_id ) ) { wp_die( __( 'You are not allowed to export this post.' ) ); }`
* @todo add security check - `check_admin_referer( 'bulk-posts' )`
*/
function bulk_actions_pdfs() {
// Get the action
$wp_list_table = _get_list_table( 'WP_Posts_List_Table' );
$action = $wp_list_table->current_action();
// Validate the action
$action_exploded = explode( '_', $action, 2 );
if (
! isset( $_GET['post'] ) || empty( $action_exploded ) || ! is_array( $action_exploded ) || 2 !== count( $action_exploded ) ||
! in_array( $action_exploded[0], array( 'generate', 'download', 'merge' ) )
) {
return;
}
// Perform the action
$post_ids = $_GET['post'];
$the_action = $action_exploded[0];
$the_type = $action_exploded[1];
switch( $the_action ) {
case 'generate':
$generated = 0;
foreach( $post_ids as $post_id ) {
if ( $this->create_document( $post_id, $the_type ) ) {
$generated++;
}
}
// Build the redirect url
$sendback = add_query_arg(
array(
'post_type' => 'shop_order',
'generated' => $generated,
'generated_type' => $the_type,
'generated_' . $the_type => 1,
'ids' => join( ',', $post_ids ),
'post_status' => $_GET['post_status'],
),
$sendback
);
break;
case 'download':
if ( '' != ( $result = $this->get_invoices_zip( $the_type, $post_ids ) ) ) {
// Build the redirect url
$sendback = add_query_arg(
array(
'post_type' => 'shop_order',
'post_status' => $_GET['post_status'],
'wcj_notice' => $result,
),
$sendback
);
}
break;
case 'merge':
$merge_ids = array();
foreach( $post_ids as $post_id ) {
if ( wcj_is_invoice_created( $post_id, $the_type ) ) {
$merge_ids[] = $post_id;
}
}
if ( ! empty( $merge_ids ) ) {
if ( '' != ( $result = $this->merge_pdfs( $the_type, $merge_ids ) ) ) {
// Build the redirect url
$sendback = add_query_arg(
array(
'post_type' => 'shop_order',
'post_status' => $_GET['post_status'],
'wcj_notice' => $result,
),
$sendback
);
}
}
break;
default:
return;
}
// Redirect client
wp_redirect( esc_url_raw( $sendback ) );
exit();
}
/**
* merge_pdfs.
*
* @version 3.5.2
* @since 3.5.0
* @see https://www.setasign.com/products/fpdi/demos/concatenate-fake/
* @todo rethink filename (i.e. 'docs.pdf')
* @todo (maybe) always save/download instead of display on output
*/
function merge_pdfs( $invoice_type_id, $post_ids ) {
if ( version_compare( PHP_VERSION, '5.3.0', '<' ) ) {
return 'merge_pdfs_php_version';
}
$files = array();
foreach( $post_ids as $post_id ) {
$the_invoice = wcj_get_pdf_invoice( $post_id, $invoice_type_id );
$files[] = $the_invoice->get_pdf( 'F' );
}
if ( empty( $files ) ) {
return 'merge_pdfs_no_files';
}
require_once( wcj_plugin_path() . '/includes/lib/FPDI/src/autoload.php' );
$fpdi_pdf = require_once( wcj_plugin_path() . '/includes/pdf-invoices/tcpdffpdi.php' );
$fpdi_pdf->SetTitle( 'docs.pdf' );
$fpdi_pdf->setPrintHeader( false );
$fpdi_pdf->setPrintFooter( false );
foreach( $files as $file ) {
$page_count = $fpdi_pdf->setSourceFile( $file );
for ( $page_nr = 1; $page_nr <= $page_count; $page_nr++ ) {
$page_id = $fpdi_pdf->ImportPage( $page_nr );
$s = $fpdi_pdf->getTemplatesize( $page_id );
$fpdi_pdf->AddPage( $s['orientation'], $s );
$fpdi_pdf->useImportedPage( $page_id );
}
}
$fpdi_pdf->Output( 'docs.pdf', ( 'yes' === get_option( 'wcj_invoicing_' . $invoice_type_id . '_save_as_enabled', 'no' ) ? 'D' : 'I' ) );
die();
}
/**
* get_invoices_zip.
*
* @version 3.5.0
* @since 2.5.7
* @todo (maybe) add timestamp to filename
* @todo add `ZipArchive` fallback
*/
function get_invoices_zip( $invoice_type_id, $post_ids ) {
if ( ! class_exists( 'ZipArchive' ) ) {
return 'ziparchive_class_missing';
}
// Creating Zip
$zip = new ZipArchive();
$zip_file_name = $invoice_type_id . '-' .
sanitize_title( str_replace( array( 'http://', 'https://' ), '', site_url() ) ) . '-' .
min( $post_ids ) . '-' . max( $post_ids ) .
'.zip';
$zip_file_path = wcj_get_invoicing_temp_dir() . '/' . $zip_file_name;
if ( file_exists( $zip_file_path ) ) {
@unlink( $zip_file_path );
}
if ( $zip->open( $zip_file_path, ZipArchive::CREATE | ZIPARCHIVE::OVERWRITE ) !== TRUE ) {
return 'ziparchive_error';
}
foreach( $post_ids as $post_id ) {
if ( wcj_is_invoice_created( $post_id, $invoice_type_id ) ) {
$the_invoice = wcj_get_pdf_invoice( $post_id, $invoice_type_id );
$file_name = $the_invoice->get_pdf( 'F' );
$zip->addFile( $file_name, $the_invoice->get_file_name() );
}
}
$zip->close();
// Sending Zip
wcj_send_file( $zip_file_name, $zip_file_path, 'zip', true );
return '';
}
/**
* create_invoices_report_tool.
*
* @version 2.3.10
* @since 2.3.10
*/
function create_invoices_report_tool() {
return $this->the_pdf_invoicing_report_tool->create_invoices_report_tool();
}
/**
* create_renumerate_invoices_tool.
*
* @version 2.3.10
* @since 2.3.10
*/
function create_renumerate_invoices_tool() {
$the_tool = include_once( 'pdf-invoices/class-wcj-pdf-invoicing-renumerate-tool.php' );
return $the_tool->create_renumerate_invoices_tool();
}
/**
* create_document_hook.
*
* @version 3.2.0
* @since 2.7.0
*/
function create_document_hook( $order_id ) {
$current_filter = current_filter();
if ( in_array( $current_filter,
array( 'woocommerce_api_create_order', 'woocommerce_cli_create_order', 'kco_before_confirm_order', 'woocommerce_checkout_order_processed' ) )
) {
$current_filter = 'woocommerce_new_order';
}
$invoice_types = wcj_get_enabled_invoice_types();
foreach ( $invoice_types as $invoice_type ) {
$the_hooks = wcj_get_invoice_create_on( $invoice_type['id'] );
foreach ( $the_hooks as $the_hook ) {
if ( 'manual' != $the_hook ) {
if ( $current_filter === $the_hook ) {
$this->create_document( $order_id, $invoice_type['id'] );
}
}
}
}
}
/**
* create_document.
*
* @version 2.5.7
*/
function create_document( $order_id, $invoice_type ) {
if ( false == wcj_is_invoice_created( $order_id, $invoice_type ) ) {
wcj_create_invoice( $order_id, $invoice_type );
return true;
}
return false;
}
/**
* delete_document.
*
* @version 2.3.0
* @since 2.3.0
*/
function delete_document( $order_id, $invoice_type ) {
if ( true == wcj_is_invoice_created( $order_id, $invoice_type ) ) {
wcj_delete_invoice( $order_id, $invoice_type );
}
}
/**
* catch_args.
*
* @version 3.4.0
*/
function catch_args() {
$this->order_id = ( isset( $_GET['order_id'] ) ) ? $_GET['order_id'] : 0;
$this->invoice_type_id = ( isset( $_GET['invoice_type_id'] ) ) ? $_GET['invoice_type_id'] : '';
$this->save_as_pdf = ( isset( $_GET['save_pdf_invoice'] ) && '1' == $_GET['save_pdf_invoice'] );
$this->get_invoice = ( isset( $_GET['get_invoice'] ) && '1' == $_GET['get_invoice'] );
if ( isset( $_GET['create_invoice_for_order_id'] ) && $this->check_user_roles( false ) ) {
$this->create_document( $_GET['create_invoice_for_order_id'], $this->invoice_type_id );
}
if ( isset( $_GET['delete_invoice_for_order_id'] ) && $this->check_user_roles( false ) ) {
$this->delete_document( $_GET['delete_invoice_for_order_id'], $this->invoice_type_id );
}
}
/**
* check_user_roles.
*
* @version 3.4.0
* @since 2.9.0
* @todo check if `current_user_can( 'administrator' )` is the same as checking role directly
*/
function check_user_roles( $allow_order_owner = true ) {
if ( $allow_order_owner && get_current_user_id() == intval( get_post_meta( $this->order_id, '_customer_user', true ) ) ) {
return true;
}
$allowed_user_roles = get_option( 'wcj_invoicing_' . $this->invoice_type_id . '_roles', array( 'administrator', 'shop_manager' ) );
if ( empty( $allowed_user_roles ) ) {
$allowed_user_roles = array( 'administrator' );
}
if ( wcj_is_user_role( $allowed_user_roles ) ) {
return true;
} else {
add_action( 'admin_notices', array( $this, 'wrong_user_role_notice' ) );
return false;
}
}
/**
* wrong_user_role_notice.
*
* @version 2.9.0
* @since 2.9.0
*/
function wrong_user_role_notice() {
echo '<div class="notice notice-error is-dismissible"><p>' . __( 'You are not allowed to view the invoice.', 'woocommerce-jetpack' ) . '</p></div>';
}
/**
* generate_pdf_on_init.
*
* @version 2.9.0
*/
function generate_pdf_on_init() {
// Check if all is OK
if ( true !== $this->get_invoice || 0 == $this->order_id || ! is_user_logged_in() || ! $this->check_user_roles() ) {
return;
}
// Get PDF
$the_invoice = wcj_get_pdf_invoice( $this->order_id, $this->invoice_type_id );
$dest = ( true === $this->save_as_pdf ? 'D' : 'I' );
$the_invoice->get_pdf( $dest );
die();
}
}
endif;
return new WCJ_PDF_Invoicing();