WooCommerce PDF Invoices & Packing Slips - Version 1.6.0

Version Description

  • WooCommerce 3.0 Compatible
  • Requires PHP version 5.3 or higher
  • Fix: Invoice number display in mobile view
  • Fix: Update formatted invoice number in order meta when number is altered
  • Tweak: Avoid PHP7 scan false positives in DomPDF
Download this release

Release Info

Developer pomegranate
Plugin Icon 128x128 WooCommerce PDF Invoices & Packing Slips
Version 1.6.0
Comparing to
See all releases

Code changes from version 1.5.39 to 1.6.0

css/style.css CHANGED
@@ -7,6 +7,15 @@
7
  width: 110px;
8
  }
9
 
 
 
 
 
 
 
 
 
 
10
  #wpo_wcpdf-data-input-box h4 {
11
  font-size: 14px;
12
  line-height: 1.4;
7
  width: 110px;
8
  }
9
 
10
+ @media screen and (max-width: 782px) {
11
+ .wp-list-table .column-pdf_invoice_number, .wp-list-table tr:not(.inline-edit-row):not(.no-items) td.column-pdf_invoice_number:not(.check-column) {
12
+ display: none;
13
+ }
14
+ .wp-list-table tr:not(.inline-edit-row):not(.no-items) td.column-pdf_invoice_number {
15
+ padding: 3px 8px 3px 35%
16
+ }
17
+ }
18
+
19
  #wpo_wcpdf-data-input-box h4 {
20
  font-size: 14px;
21
  line-height: 1.4;
includes/class-wcpdf-export.php CHANGED
@@ -1,4 +1,10 @@
1
  <?php
 
 
 
 
 
 
2
  /**
3
  * PDF Export class
4
  */
@@ -22,7 +28,7 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
22
  */
23
  public function __construct() {
24
  global $woocommerce;
25
- $this->order = new WC_Order('');
26
  $this->general_settings = get_option('wpo_wcpdf_general_settings');
27
  $this->template_settings = get_option('wpo_wcpdf_template_settings');
28
  $this->debug_settings = get_option('wpo_wcpdf_debug_settings');
@@ -269,7 +275,7 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
269
 
270
  $output_html = array();
271
  foreach ($order_ids as $order_id) {
272
- $this->order = new WC_Order( $order_id );
273
  do_action( 'wpo_wcpdf_process_template_order', $template_type, $order_id );
274
 
275
  $template = $this->template_path . '/' . $template_type . '.php';
@@ -288,7 +294,7 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
288
 
289
  // store meta to be able to check if an invoice for an order has been created already
290
  if ( $template_type == 'invoice' ) {
291
- update_post_meta( $order_id, '_wcpdf_invoice_exists', 1 );
292
  }
293
 
294
 
@@ -440,10 +446,10 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
440
  }
441
 
442
  // Get user_id of order
443
- $this->order = new WC_Order ( $order_ids[0] );
444
 
445
  // Check if current user is owner of order IMPORTANT!!!
446
- if ( $this->order->user_id != get_current_user_id() ) {
447
  wp_die( __( 'You do not have sufficient permissions to access this page.', 'wpo_wcpdf' ) );
448
  }
449
 
@@ -510,7 +516,7 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
510
  break;
511
  default:
512
  $name = $template_type;
513
- $number = $this->order->get_order_number();
514
  break;
515
  }
516
 
@@ -550,18 +556,20 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
550
  return $attachments;
551
  }
552
 
553
- if ( !isset($order->id) ) {
 
 
554
  return $attachments;
555
  }
556
 
557
  // WooCommerce Booking compatibility
558
- if ( get_post_type( $order->id ) == 'wc_booking' && isset($order->order) ) {
559
  // $order is actually a WC_Booking object!
560
  $order = $order->order;
561
  }
562
 
563
  // do not process low stock notifications, user emails etc!
564
- if ( in_array( $status, array( 'no_stock', 'low_stock', 'backorder', 'customer_new_account', 'customer_reset_password' ) ) || get_post_type( $order->id ) != 'shop_order' ) {
565
  return $attachments;
566
  }
567
 
@@ -610,7 +618,7 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
610
  if( in_array( $status, $allowed_statuses ) && $attach_document ) {
611
  do_action( 'wpo_wcpdf_before_attachment_creation', $order, $status, $template_type );
612
  // create pdf data
613
- $pdf_data = $this->get_pdf( $template_type, (array) $order->id );
614
 
615
  if ( !$pdf_data ) {
616
  // something went wrong, continue trying with other documents
@@ -618,7 +626,7 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
618
  }
619
 
620
  // compose filename
621
- $pdf_filename = $this->build_filename( $template_type, (array) $order->id, 'attachment' );
622
 
623
  $pdf_path = $tmp_path . $pdf_filename;
624
  file_put_contents ( $pdf_path, $pdf_data );
@@ -632,13 +640,14 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
632
  }
633
 
634
  public function set_invoice_number( $order_id ) {
 
 
635
  // first check: get invoice number from post meta
636
- $invoice_number = get_post_meta( $order_id, '_wcpdf_invoice_number', true );
637
 
638
  // If a third-party plugin claims to generate invoice numbers, use it instead
639
  $third_party = apply_filters('woocommerce_invoice_number_by_plugin', false);
640
  if ($third_party) {
641
- $order = new WC_Order($order_id);
642
  $invoice_number = apply_filters('woocommerce_generate_invoice_number', null, $order);
643
  }
644
 
@@ -653,7 +662,7 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
653
  // First time! We start numbering from order_number or order_id
654
 
655
  // Check if $order_number is an integer
656
- $order_number = ltrim($this->order->get_order_number(), '#');
657
  if ( ctype_digit( (string)$order_number ) ) {
658
  // order_number == integer: use as starting point.
659
  $invoice_number = $order_number;
@@ -687,8 +696,8 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
687
  // $order_number = ltrim($this->order->get_order_number(), '#');
688
  // $this->log( $order_id, "Invoice number {$invoice_number} set for order {$order_number} (id {$order_id})" );
689
 
690
- update_post_meta($order_id, '_wcpdf_invoice_number', $invoice_number);
691
- update_post_meta($order_id, '_wcpdf_formatted_invoice_number', $this->get_invoice_number( $order_id ) );
692
 
693
  // increase next_order_number
694
  $update_args = array(
@@ -709,6 +718,7 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
709
  }
710
 
711
  public function get_invoice_number( $order_id ) {
 
712
  // Call the woocommerce_invoice_number filter and let third-party plugins set a number.
713
  // Default is null, so we can detect whether a plugin has set the invoice number
714
  $third_party_invoice_number = apply_filters( 'woocommerce_invoice_number', null, $order_id );
@@ -716,19 +726,20 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
716
  return $third_party_invoice_number;
717
  }
718
 
719
- // get invoice number from post meta
720
- if ( $invoice_number = get_post_meta( $order_id, '_wcpdf_invoice_number', true ) ) {
 
721
  // check if we have already loaded this order
722
- if ( $this->order->id == $order_id ) {
723
  $order_number = $this->order->get_order_number();
724
- $order_date = $this->order->order_date;
725
  } else {
726
- $order = new WC_Order( $order_id );
727
  $order_number = $order->get_order_number();
728
- $order_date = $order->order_date;
729
  }
730
-
731
- return apply_filters( 'wpo_wcpdf_invoice_number', $invoice_number, $order_number, $order_id, $order_date );
732
  } else {
733
  // no invoice number for this order
734
  return false;
@@ -739,7 +750,7 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
739
  * Add invoice number to WC REST API
740
  */
741
  public function woocommerce_api_invoice_numer ( $data, $order ) {
742
- if ( $invoice_number = $this->get_invoice_number( $order->id ) ) {
743
  $data['wpo_wcpdf_invoice_number'] = $invoice_number;
744
  } else {
745
  $data['wpo_wcpdf_invoice_number'] = '';
@@ -752,24 +763,26 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
752
  * https://wordpress.org/support/topic/subscription-renewal-duplicate-invoice-number?replies=6#post-6138110
753
  */
754
  public function woocommerce_subscriptions_renewal_order_created ( $renewal_order, $original_order, $product_id, $new_order_role ) {
755
- $this->reset_invoice_data( $renewal_order->id );
756
  return $renewal_order;
757
  }
758
 
759
  public function wcs_renewal_order_created ( $renewal_order, $subscription ) {
760
- $this->reset_invoice_data( $renewal_order->id );
761
  return $renewal_order;
762
  }
763
 
764
  public function reset_invoice_data ( $order_id ) {
 
765
  // delete invoice number, invoice date & invoice exists meta
766
- delete_post_meta( $order_id, '_wcpdf_invoice_number' );
767
- delete_post_meta( $order_id, '_wcpdf_formatted_invoice_number' );
768
- delete_post_meta( $order_id, '_wcpdf_invoice_date' );
769
- delete_post_meta( $order_id, '_wcpdf_invoice_exists' );
770
  }
771
 
772
  public function format_invoice_number( $invoice_number, $order_number, $order_id, $order_date ) {
 
773
  // get format settings
774
  $formats['prefix'] = isset($this->template_settings['invoice_number_formatting_prefix'])?$this->template_settings['invoice_number_formatting_prefix']:'';
775
  $formats['suffix'] = isset($this->template_settings['invoice_number_formatting_suffix'])?$this->template_settings['invoice_number_formatting_suffix']:'';
@@ -779,7 +792,7 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
779
  $order_year = date_i18n( 'Y', strtotime( $order_date ) );
780
  $order_month = date_i18n( 'm', strtotime( $order_date ) );
781
  $order_day = date_i18n( 'd', strtotime( $order_date ) );
782
- $invoice_date = get_post_meta($order_id,'_wcpdf_invoice_date',true);
783
  $invoice_date = empty($invoice_date) ? current_time('mysql') : $invoice_date;
784
  $invoice_year = date_i18n( 'Y', strtotime( $invoice_date ) );
785
  $invoice_month = date_i18n( 'm', strtotime( $invoice_date ) );
@@ -806,8 +819,8 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
806
  }
807
 
808
  public function get_display_number( $order_id ) {
809
- if ( !isset($this->order->id) ) {
810
- $this->order = new WC_Order ( $order_id );
811
  }
812
 
813
  if ( isset($this->template_settings['display_number']) && $this->template_settings['display_number'] == 'invoice_number' ) {
@@ -834,10 +847,16 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
834
  }
835
 
836
  /**
837
- * Get the current order
838
  */
839
- public function get_order() {
840
- return $this->order;
 
 
 
 
 
 
841
  }
842
 
843
  /**
@@ -899,9 +918,6 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
899
 
900
  // Checking fo existance, thanks to MDesigner0
901
  if(!empty($product)) {
902
- // Set the thumbnail id DEPRICATED (does not support thumbnail sizes), use thumbnail_path or thumbnail instead
903
- $data['thumbnail_id'] = $this->get_thumbnail_id( $product );
904
-
905
  // Thumbnail (full img tag)
906
  $data['thumbnail'] = $this->get_thumbnail ( $product );
907
 
@@ -915,7 +931,7 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
915
  $data['weight'] = $product->get_weight();
916
 
917
  // Set item dimensions
918
- $data['dimensions'] = $product->get_dimensions();
919
 
920
  // Pass complete product object
921
  $data['product'] = $product;
@@ -968,7 +984,7 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
968
  public function wc_price( $price, $args = array() ) {
969
  if ( version_compare( WOOCOMMERCE_VERSION, '2.1' ) >= 0 ) {
970
  // WC 2.1 or newer is used
971
- $args['currency'] = $this->order->get_order_currency();
972
  $formatted_price = wc_price( $price, $args );
973
  } else {
974
  $formatted_price = woocommerce_price( $price );
@@ -1091,11 +1107,11 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
1091
  public function get_thumbnail_id ( $product ) {
1092
  global $woocommerce;
1093
 
1094
- if ( $product->variation_id && has_post_thumbnail( $product->variation_id ) ) {
1095
- $thumbnail_id = get_post_thumbnail_id ( $product->variation_id );
1096
- } elseif ( has_post_thumbnail( $product->id ) ) {
1097
- $thumbnail_id = get_post_thumbnail_id ( $product->id );
1098
- } elseif ( ( $parent_id = wp_get_post_parent_id( $product->id ) ) && has_post_thumbnail( $parent_id ) ) {
1099
  $thumbnail_id = get_post_thumbnail_id ( $parent_id );
1100
  } else {
1101
  $thumbnail_id = false;
@@ -1165,18 +1181,16 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
1165
  }
1166
  }
1167
 
1168
- $item_meta = $order->get_item_meta( $item_id );
1169
-
1170
- if (isset($item_meta['_bundled_by'])) {
1171
  $classes = $classes . ' bundled-item';
1172
 
1173
  // check bundled item visibility
1174
- if ( ! empty( $item_meta[ '_bundled_item_hidden' ] ) ) {
1175
  $classes = $classes . ' hidden';
1176
  }
1177
 
1178
  return $classes;
1179
- } elseif (isset($item_meta['_bundled_items'])) {
1180
  return $classes . ' product-bundle';
1181
  }
1182
 
@@ -1200,9 +1214,7 @@ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Export' ) ) {
1200
  }
1201
  }
1202
 
1203
- $item_meta = $order->get_item_meta( $item_id );
1204
-
1205
- if (isset($item_meta['_chained_product_of'])) {
1206
  return $classes . ' chained-product';
1207
  }
1208
 
1
  <?php
2
+ use WPO\WC\PDF_Invoices\Compatibility\WC_Core as WCX;
3
+ use WPO\WC\PDF_Invoices\Compatibility\Order as WCX_Order;
4
+ use WPO\WC\PDF_Invoices\Compatibility\Product as WCX_Product;
5
+
6
+ defined( 'ABSPATH' ) or exit;
7
+
8
  /**
9
  * PDF Export class
10
  */
28
  */
29
  public function __construct() {
30
  global $woocommerce;
31
+ $this->order = WCX::get_order('');
32
  $this->general_settings = get_option('wpo_wcpdf_general_settings');
33
  $this->template_settings = get_option('wpo_wcpdf_template_settings');
34
  $this->debug_settings = get_option('wpo_wcpdf_debug_settings');
275
 
276
  $output_html = array();
277
  foreach ($order_ids as $order_id) {
278
+ $this->order = WCX::get_order( $order_id );
279
  do_action( 'wpo_wcpdf_process_template_order', $template_type, $order_id );
280
 
281
  $template = $this->template_path . '/' . $template_type . '.php';
294
 
295
  // store meta to be able to check if an invoice for an order has been created already
296
  if ( $template_type == 'invoice' ) {
297
+ WCX_Order::update_meta_data( $this->order, '_wcpdf_invoice_exists', 1 );
298
  }
299
 
300
 
446
  }
447
 
448
  // Get user_id of order
449
+ $this->order = WCX::get_order ( $order_ids[0] );
450
 
451
  // Check if current user is owner of order IMPORTANT!!!
452
+ if ( WCX_Order::get_prop( $this->order, 'customer_id' ) != get_current_user_id() ) {
453
  wp_die( __( 'You do not have sufficient permissions to access this page.', 'wpo_wcpdf' ) );
454
  }
455
 
516
  break;
517
  default:
518
  $name = $template_type;
519
+ $number = method_exists( $this->order, 'get_order_number' ) ? $this->order->get_order_number() : '';
520
  break;
521
  }
522
 
556
  return $attachments;
557
  }
558
 
559
+ $order_id = WCX_Order::get_id($order);
560
+
561
+ if ( get_class( $order ) !== 'WC_Order' && $order_id == false ) {
562
  return $attachments;
563
  }
564
 
565
  // WooCommerce Booking compatibility
566
+ if ( get_post_type( $order_id ) == 'wc_booking' && isset($order->order) ) {
567
  // $order is actually a WC_Booking object!
568
  $order = $order->order;
569
  }
570
 
571
  // do not process low stock notifications, user emails etc!
572
+ if ( in_array( $status, array( 'no_stock', 'low_stock', 'backorder', 'customer_new_account', 'customer_reset_password' ) ) || get_post_type( $order_id ) != 'shop_order' ) {
573
  return $attachments;
574
  }
575
 
618
  if( in_array( $status, $allowed_statuses ) && $attach_document ) {
619
  do_action( 'wpo_wcpdf_before_attachment_creation', $order, $status, $template_type );
620
  // create pdf data
621
+ $pdf_data = $this->get_pdf( $template_type, (array) $order_id );
622
 
623
  if ( !$pdf_data ) {
624
  // something went wrong, continue trying with other documents
626
  }
627
 
628
  // compose filename
629
+ $pdf_filename = $this->build_filename( $template_type, (array) $order_id, 'attachment' );
630
 
631
  $pdf_path = $tmp_path . $pdf_filename;
632
  file_put_contents ( $pdf_path, $pdf_data );
640
  }
641
 
642
  public function set_invoice_number( $order_id ) {
643
+ $order = $this->get_order( $order_id );
644
+
645
  // first check: get invoice number from post meta
646
+ $invoice_number = WCX_Order::get_meta( $order, '_wcpdf_invoice_number', true );
647
 
648
  // If a third-party plugin claims to generate invoice numbers, use it instead
649
  $third_party = apply_filters('woocommerce_invoice_number_by_plugin', false);
650
  if ($third_party) {
 
651
  $invoice_number = apply_filters('woocommerce_generate_invoice_number', null, $order);
652
  }
653
 
662
  // First time! We start numbering from order_number or order_id
663
 
664
  // Check if $order_number is an integer
665
+ $order_number = ltrim($order->get_order_number(), '#');
666
  if ( ctype_digit( (string)$order_number ) ) {
667
  // order_number == integer: use as starting point.
668
  $invoice_number = $order_number;
696
  // $order_number = ltrim($this->order->get_order_number(), '#');
697
  // $this->log( $order_id, "Invoice number {$invoice_number} set for order {$order_number} (id {$order_id})" );
698
 
699
+ WCX_Order::update_meta_data( $order, '_wcpdf_invoice_number', $invoice_number );
700
+ WCX_Order::update_meta_data( $order, '_wcpdf_formatted_invoice_number', $this->get_invoice_number( $order_id ) );
701
 
702
  // increase next_order_number
703
  $update_args = array(
718
  }
719
 
720
  public function get_invoice_number( $order_id ) {
721
+ $order = $this->get_order( $order_id );
722
  // Call the woocommerce_invoice_number filter and let third-party plugins set a number.
723
  // Default is null, so we can detect whether a plugin has set the invoice number
724
  $third_party_invoice_number = apply_filters( 'woocommerce_invoice_number', null, $order_id );
726
  return $third_party_invoice_number;
727
  }
728
 
729
+ // get invoice number from order
730
+ $invoice_number = WCX_Order::get_meta( $order, '_wcpdf_invoice_number', true );
731
+ if ( $invoice_number ) {
732
  // check if we have already loaded this order
733
+ if ( !empty( $this->order ) && WCX_Order::get_id( $this->order ) == $order_id ) {
734
  $order_number = $this->order->get_order_number();
735
+ $order_date = WCX_Order::get_prop( $this->order, 'date_created' );
736
  } else {
737
+ $order = WCX::get_order( $order_id );
738
  $order_number = $order->get_order_number();
739
+ $order_date = WCX_Order::get_prop( $order, 'date_created' );
740
  }
741
+ $mysql_order_date = $order_date->date( "Y-m-d H:i:s" );
742
+ return apply_filters( 'wpo_wcpdf_invoice_number', $invoice_number, $order_number, $order_id, $mysql_order_date );
743
  } else {
744
  // no invoice number for this order
745
  return false;
750
  * Add invoice number to WC REST API
751
  */
752
  public function woocommerce_api_invoice_numer ( $data, $order ) {
753
+ if ( $invoice_number = $this->get_invoice_number( WCX_Order::get_id( $order ) ) ) {
754
  $data['wpo_wcpdf_invoice_number'] = $invoice_number;
755
  } else {
756
  $data['wpo_wcpdf_invoice_number'] = '';
763
  * https://wordpress.org/support/topic/subscription-renewal-duplicate-invoice-number?replies=6#post-6138110
764
  */
765
  public function woocommerce_subscriptions_renewal_order_created ( $renewal_order, $original_order, $product_id, $new_order_role ) {
766
+ $this->reset_invoice_data( WCX_Order::get_id( $renewal_order ) );
767
  return $renewal_order;
768
  }
769
 
770
  public function wcs_renewal_order_created ( $renewal_order, $subscription ) {
771
+ $this->reset_invoice_data( WCX_Order::get_id( $renewal_order ) );
772
  return $renewal_order;
773
  }
774
 
775
  public function reset_invoice_data ( $order_id ) {
776
+ $order = $this->get_order( $order_id );
777
  // delete invoice number, invoice date & invoice exists meta
778
+ WCX_Order::delete_meta_data( $order, '_wcpdf_invoice_number' );
779
+ WCX_Order::delete_meta_data( $order, '_wcpdf_formatted_invoice_number' );
780
+ WCX_Order::delete_meta_data( $order, '_wcpdf_invoice_date' );
781
+ WCX_Order::delete_meta_data( $order, '_wcpdf_invoice_exists' );
782
  }
783
 
784
  public function format_invoice_number( $invoice_number, $order_number, $order_id, $order_date ) {
785
+ $order = $this->get_order( $order_id );
786
  // get format settings
787
  $formats['prefix'] = isset($this->template_settings['invoice_number_formatting_prefix'])?$this->template_settings['invoice_number_formatting_prefix']:'';
788
  $formats['suffix'] = isset($this->template_settings['invoice_number_formatting_suffix'])?$this->template_settings['invoice_number_formatting_suffix']:'';
792
  $order_year = date_i18n( 'Y', strtotime( $order_date ) );
793
  $order_month = date_i18n( 'm', strtotime( $order_date ) );
794
  $order_day = date_i18n( 'd', strtotime( $order_date ) );
795
+ $invoice_date = WCX_Order::get_meta( $order, '_wcpdf_invoice_date', true );
796
  $invoice_date = empty($invoice_date) ? current_time('mysql') : $invoice_date;
797
  $invoice_year = date_i18n( 'Y', strtotime( $invoice_date ) );
798
  $invoice_month = date_i18n( 'm', strtotime( $invoice_date ) );
819
  }
820
 
821
  public function get_display_number( $order_id ) {
822
+ if ( !isset($this->order) ) {
823
+ $this->order = WCX::get_order ( $order_id );
824
  }
825
 
826
  if ( isset($this->template_settings['display_number']) && $this->template_settings['display_number'] == 'invoice_number' ) {
847
  }
848
 
849
  /**
850
+ * Get the current order or order by id
851
  */
852
+ public function get_order( $order_id = null ) {
853
+ if ( empty( $order_id ) && isset( $this->order ) ) {
854
+ return $this->order;
855
+ } elseif ( is_object( $this->order ) && WCX_Order::get_id( $this->order ) == $order_id ) {
856
+ return $this->order;
857
+ } else {
858
+ return WCX::get_order( $order_id );
859
+ }
860
  }
861
 
862
  /**
918
 
919
  // Checking fo existance, thanks to MDesigner0
920
  if(!empty($product)) {
 
 
 
921
  // Thumbnail (full img tag)
922
  $data['thumbnail'] = $this->get_thumbnail ( $product );
923
 
931
  $data['weight'] = $product->get_weight();
932
 
933
  // Set item dimensions
934
+ $data['dimensions'] = WCX_Product::get_dimensions( $product );
935
 
936
  // Pass complete product object
937
  $data['product'] = $product;
984
  public function wc_price( $price, $args = array() ) {
985
  if ( version_compare( WOOCOMMERCE_VERSION, '2.1' ) >= 0 ) {
986
  // WC 2.1 or newer is used
987
+ $args['currency'] = WCX_Order::get_prop( $this->order, 'currency' );
988
  $formatted_price = wc_price( $price, $args );
989
  } else {
990
  $formatted_price = woocommerce_price( $price );
1107
  public function get_thumbnail_id ( $product ) {
1108
  global $woocommerce;
1109
 
1110
+ $product_id = WCX_Product::get_id( $product );
1111
+
1112
+ if ( has_post_thumbnail( $product_id ) ) {
1113
+ $thumbnail_id = get_post_thumbnail_id ( $product_id );
1114
+ } elseif ( ( $parent_id = wp_get_post_parent_id( $product_id ) ) && has_post_thumbnail( $parent_id ) ) {
1115
  $thumbnail_id = get_post_thumbnail_id ( $parent_id );
1116
  } else {
1117
  $thumbnail_id = false;
1181
  }
1182
  }
1183
 
1184
+ if ( $bundled_by = WCX_Order::get_item_meta( $order, $item_id, '_bundled_by', true ) ) {
 
 
1185
  $classes = $classes . ' bundled-item';
1186
 
1187
  // check bundled item visibility
1188
+ if ( $hidden = WCX_Order::get_item_meta( $order, $item_id, '_bundled_item_hidden', true ) ) {
1189
  $classes = $classes . ' hidden';
1190
  }
1191
 
1192
  return $classes;
1193
+ } elseif ( $bundled_items = WCX_Order::get_item_meta( $order, $item_id, '_bundled_items', true ) ) {
1194
  return $classes . ' product-bundle';
1195
  }
1196
 
1214
  }
1215
  }
1216
 
1217
+ if ( $chained_product_of = WCX_Order::get_item_meta( $order, $item_id, '_chained_product_of', true ) ) {
 
 
1218
  return $classes . ' chained-product';
1219
  }
1220
 
includes/class-wcpdf-functions.php ADDED
@@ -0,0 +1,813 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ use WPO\WC\PDF_Invoices\Compatibility\WC_Core as WCX;
3
+ use WPO\WC\PDF_Invoices\Compatibility\Order as WCX_Order;
4
+ use WPO\WC\PDF_Invoices\Compatibility\Product as WCX_Product;
5
+
6
+ defined( 'ABSPATH' ) or exit;
7
+
8
+ if ( ! class_exists( 'WooCommerce_PDF_Invoices_Functions' ) ) :
9
+
10
+ class WooCommerce_PDF_Invoices_Functions {
11
+
12
+ /**
13
+ * Get template name from slug
14
+ */
15
+ public function get_template_name ( $template_type ) {
16
+ switch ( $template_type ) {
17
+ case 'invoice':
18
+ $template_name = apply_filters( 'wpo_wcpdf_invoice_title', __( 'Invoice', 'wpo_wcpdf' ) );
19
+ break;
20
+ case 'packing-slip':
21
+ $template_name = apply_filters( 'wpo_wcpdf_packing_slip_title', __( 'Packing Slip', 'wpo_wcpdf' ) );
22
+ break;
23
+ default:
24
+ // try to 'unslug' the name
25
+ $template_name = ucwords( str_replace( array( '_', '-' ), ' ', $template_type ) );
26
+ break;
27
+ }
28
+
29
+ return apply_filters( 'wpo_wcpdf_template_name', $template_name, $template_type );
30
+ }
31
+
32
+ /**
33
+ * Output template styles
34
+ */
35
+ public function template_styles() {
36
+ $css = apply_filters( 'wpo_wcpdf_template_styles_file', WPO_WCPDF()->export->template_path. '/' .'style.css' );
37
+
38
+ ob_start();
39
+ if (file_exists($css)) {
40
+ include($css);
41
+ }
42
+ $html = ob_get_clean();
43
+ $html = apply_filters( 'wpo_wcpdf_template_styles', $html );
44
+
45
+ echo $html;
46
+ }
47
+
48
+ /**
49
+ * Return logo id
50
+ */
51
+ public function get_header_logo_id() {
52
+ if (isset(WPO_WCPDF()->settings->template_settings['header_logo'])) {
53
+ return apply_filters( 'wpo_wcpdf_header_logo_id', WPO_WCPDF()->settings->template_settings['header_logo'] );
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Show logo html
59
+ */
60
+ public function header_logo() {
61
+ if ($this->get_header_logo_id()) {
62
+ $attachment_id = $this->get_header_logo_id();
63
+ $company = isset(WPO_WCPDF()->settings->template_settings['shop_name'])? WPO_WCPDF()->settings->template_settings['shop_name'] : '';
64
+ if( $attachment_id ) {
65
+ $attachment = wp_get_attachment_image_src( $attachment_id, 'full', false );
66
+
67
+ $attachment_src = $attachment[0];
68
+ $attachment_width = $attachment[1];
69
+ $attachment_height = $attachment[2];
70
+
71
+ $attachment_path = get_attached_file( $attachment_id );
72
+
73
+ if ( apply_filters('wpo_wcpdf_use_path', true) && file_exists($attachment_path) ) {
74
+ $src = $attachment_path;
75
+ } else {
76
+ $src = $attachment_src;
77
+ }
78
+
79
+ printf('<img src="%1$s" width="%2$d" height="%3$d" alt="%4$s" />', $src, $attachment_width, $attachment_height, esc_attr( $company ) );
80
+ }
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Return/Show custom company name or default to blog name
86
+ */
87
+ public function get_shop_name() {
88
+ if (!empty(WPO_WCPDF()->settings->template_settings['shop_name'])) {
89
+ $name = trim( WPO_WCPDF()->settings->template_settings['shop_name'] );
90
+ return apply_filters( 'wpo_wcpdf_shop_name', wptexturize( $name ) );
91
+ } else {
92
+ return apply_filters( 'wpo_wcpdf_shop_name', get_bloginfo( 'name' ) );
93
+ }
94
+ }
95
+ public function shop_name() {
96
+ echo $this->get_shop_name();
97
+ }
98
+
99
+ /**
100
+ * Return/Show shop/company address if provided
101
+ */
102
+ public function get_shop_address() {
103
+ $shop_address = apply_filters( 'wpo_wcpdf_shop_address', wpautop( wptexturize( WPO_WCPDF()->settings->template_settings['shop_address'] ) ) );
104
+ if (!empty($shop_address)) {
105
+ return $shop_address;
106
+ } else {
107
+ return false;
108
+ }
109
+ }
110
+ public function shop_address() {
111
+ echo $this->get_shop_address();
112
+ }
113
+
114
+ /**
115
+ * Check if billing address and shipping address are equal
116
+ */
117
+ public function ships_to_different_address() {
118
+ $order = &WPO_WCPDF()->export->order;
119
+ $order_id = WCX_Order::get_id( $order );
120
+ // always prefer parent address for refunds
121
+ if ( get_post_type( $order_id ) == 'shop_order_refund' && $parent_order_id = wp_get_post_parent_id( $order_id ) ) {
122
+ $current_order = $order;
123
+ $order = WCX::get_order( $parent_order_id );
124
+ }
125
+
126
+ $address_comparison_fields = apply_filters( 'wpo_wcpdf_address_comparison_fields', array(
127
+ 'first_name',
128
+ 'last_name',
129
+ 'company',
130
+ 'address_1',
131
+ 'address_2',
132
+ 'city',
133
+ 'state',
134
+ 'postcode',
135
+ 'country'
136
+ ) );
137
+
138
+ foreach ($address_comparison_fields as $address_field) {
139
+ $billing_field = WCX_Order::get_prop( $order, "billing_{$address_field}", 'view');
140
+ $shipping_field = WCX_Order::get_prop( $order, "shipping_{$address_field}", 'view');
141
+ if ( $shipping_field != $billing_field ) {
142
+ // this address field is different -> ships to different address!
143
+ $order = isset($current_order) ? $current_order : $order; // reset back to refund if necessery
144
+ return true;
145
+ }
146
+ }
147
+
148
+ //if we got here, it means the addresses are equal -> doesn't ship to different address!
149
+ $order = isset($current_order) ? $current_order : $order; // reset back to refund if necessery
150
+ return apply_filters( 'wpo_wcpdf_ships_to_different_address', false, $order );
151
+ }
152
+
153
+ /**
154
+ * Return/Show billing address
155
+ */
156
+ public function get_billing_address() {
157
+ $order_id = WCX_Order::get_id( WPO_WCPDF()->export->order );
158
+ // always prefer parent billing address for refunds
159
+ if ( get_post_type( $order_id ) == 'shop_order_refund' && $parent_order_id = wp_get_post_parent_id( $order_id ) ) {
160
+ // temporarily switch order to make all filters / order calls work correctly
161
+ $current_order = WPO_WCPDF()->export->order;
162
+ WPO_WCPDF()->export->order = WCX::get_order( $parent_order_id );
163
+ $address = apply_filters( 'wpo_wcpdf_billing_address', WPO_WCPDF()->export->order->get_formatted_billing_address() );
164
+ // switch back & unset
165
+ WPO_WCPDF()->export->order = $current_order;
166
+ unset($current_order);
167
+ } elseif ( $address = WPO_WCPDF()->export->order->get_formatted_billing_address() ) {
168
+ // regular shop_order
169
+ $address = apply_filters( 'wpo_wcpdf_billing_address', $address );
170
+ } else {
171
+ // no address
172
+ $address = apply_filters( 'wpo_wcpdf_billing_address', __('N/A', 'wpo_wcpdf') );
173
+ }
174
+
175
+ return $address;
176
+ }
177
+ public function billing_address() {
178
+ echo $this->get_billing_address();
179
+ }
180
+
181
+ /**
182
+ * Return/Show billing email
183
+ */
184
+ public function get_billing_email() {
185
+ $billing_email = WCX_Order::get_prop( WPO_WCPDF()->export->order, 'billing_email', 'view' );
186
+
187
+ if ( !$billing_email && $parent_order_id = wp_get_post_parent_id( WCX_Order::get_id( WPO_WCPDF()->export->order ) ) ) {
188
+ // try parent
189
+ $parent_order = WCX::get_order( $parent_order_id );
190
+ $billing_email = WCX_Order::get_prop( $parent_order, 'billing_email', 'view' );
191
+ }
192
+
193
+ return apply_filters( 'wpo_wcpdf_billing_email', $billing_email );
194
+ }
195
+ public function billing_email() {
196
+ echo $this->get_billing_email();
197
+ }
198
+
199
+ /**
200
+ * Return/Show billing phone
201
+ */
202
+ public function get_billing_phone() {
203
+ $billing_phone = WCX_Order::get_prop( WPO_WCPDF()->export->order, 'billing_phone', 'view' );
204
+
205
+ if ( !$billing_phone && $parent_order_id = wp_get_post_parent_id( WCX_Order::get_id( WPO_WCPDF()->export->order ) ) ) {
206
+ // try parent
207
+ $parent_order = WCX::get_order( $parent_order_id );
208
+ $billing_phone = WCX_Order::get_prop( $parent_order, 'billing_phone', 'view' );
209
+ }
210
+
211
+ return apply_filters( 'wpo_wcpdf_billing_phone', $billing_phone );
212
+ }
213
+ public function billing_phone() {
214
+ echo $this->get_billing_phone();
215
+ }
216
+
217
+ /**
218
+ * Return/Show shipping address
219
+ */
220
+ public function get_shipping_address() {
221
+ $order_id = WCX_Order::get_id( WPO_WCPDF()->export->order );
222
+
223
+ // always prefer parent shipping address for refunds
224
+ if ( get_post_type( $order_id ) == 'shop_order_refund' && $parent_order_id = wp_get_post_parent_id( $order_id ) ) {
225
+ // temporarily switch order to make all filters / order calls work correctly
226
+ $current_order = WPO_WCPDF()->export->order;
227
+ WPO_WCPDF()->export->order = WCX::get_order( $parent_order_id );
228
+ $address = apply_filters( 'wpo_wcpdf_shipping_address', WPO_WCPDF()->export->order->get_formatted_shipping_address() );
229
+ // switch back & unset
230
+ WPO_WCPDF()->export->order = $current_order;
231
+ unset($current_order);
232
+ } elseif ( $address = WPO_WCPDF()->export->order->get_formatted_shipping_address() ) {
233
+ // regular shop_order
234
+ $address = apply_filters( 'wpo_wcpdf_shipping_address', $address );
235
+ } else {
236
+ // no address
237
+ $address = apply_filters( 'wpo_wcpdf_shipping_address', __('N/A', 'wpo_wcpdf') );
238
+ }
239
+
240
+ return $address;
241
+ }
242
+ public function shipping_address() {
243
+ echo $this->get_shipping_address();
244
+ }
245
+
246
+ /**
247
+ * Return/Show a custom field
248
+ */
249
+ public function get_custom_field( $field_name ) {
250
+ $custom_field = WCX_Order::get_meta( WPO_WCPDF()->export->order, $field_name, true );
251
+
252
+ if ( !$custom_field && $parent_order_id = wp_get_post_parent_id( WCX_Order::get_id( WPO_WCPDF()->export->order ) ) ) {
253
+ // try parent
254
+ $parent_order = WCX::get_order( $parent_order_id );
255
+ $custom_field = WCX_Order::get_meta( $parent_order, $field_name, true );
256
+ }
257
+
258
+ return apply_filters( 'wpo_wcpdf_billing_custom_field', $custom_field );
259
+ }
260
+ public function custom_field( $field_name, $field_label = '', $display_empty = false ) {
261
+ $custom_field = $this->get_custom_field( $field_name );
262
+ if (!empty($field_label)){
263
+ // add a a trailing space to the label
264
+ $field_label .= ' ';
265
+ }
266
+
267
+ if (!empty($custom_field) || $display_empty) {
268
+ echo $field_label . nl2br ($custom_field);
269
+ }
270
+ }
271
+
272
+ /**
273
+ * Return/Show order notes
274
+ */
275
+ public function get_order_notes( $filter = 'customer' ) {
276
+ $order_id = WCX_Order::get_id( WPO_WCPDF()->export->order );
277
+ if ( get_post_type( $order_id ) == 'shop_order_refund' && $parent_order_id = wp_get_post_parent_id( $order_id ) ) {
278
+ $post_id = $parent_order_id;
279
+ } else {
280
+ $post_id = $order_id;
281
+ }
282
+
283
+ $args = array(
284
+ 'post_id' => $post_id,
285
+ 'approve' => 'approve',
286
+ 'type' => 'order_note'
287
+ );
288
+
289
+ remove_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ), 10, 1 );
290
+
291
+ $notes = get_comments( $args );
292
+
293
+ add_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ), 10, 1 );
294
+
295
+ if ( $notes ) {
296
+ foreach( $notes as $key => $note ) {
297
+ if ( $filter == 'customer' && !get_comment_meta( $note->comment_ID, 'is_customer_note', true ) ) {
298
+ unset($notes[$key]);
299
+ }
300
+ if ( $filter == 'private' && get_comment_meta( $note->comment_ID, 'is_customer_note', true ) ) {
301
+ unset($notes[$key]);
302
+ }
303
+ }
304
+ return $notes;
305
+ }
306
+ }
307
+ public function order_notes( $filter = 'customer' ) {
308
+ $notes = $this->get_order_notes( $filter );
309
+ if ( $notes ) {
310
+ foreach( $notes as $note ) {
311
+ ?>
312
+ <div class="note_content">
313
+ <?php echo wpautop( wptexturize( wp_kses_post( $note->comment_content ) ) ); ?>
314
+ </div>
315
+ <?php
316
+ }
317
+ }
318
+ }
319
+
320
+ /**
321
+ * Return/Show the current date
322
+ */
323
+ public function get_current_date() {
324
+ return apply_filters( 'wpo_wcpdf_date', date_i18n( get_option( 'date_format' ) ) );
325
+ }
326
+ public function current_date() {
327
+ echo $this->get_current_date();
328
+ }
329
+
330
+ /**
331
+ * Return/Show payment method
332
+ */
333
+ public function get_payment_method() {
334
+ $order_id = WCX_Order::get_id( WPO_WCPDF()->export->order );
335
+ $payment_method_label = __( 'Payment method', 'wpo_wcpdf' );
336
+
337
+ // use parent for credit notes
338
+ if ( get_post_type( $order_id ) == 'shop_order_refund' && $parent_order_id = wp_get_post_parent_id( WCX_Order::get_id( WPO_WCPDF()->export->order ) ) ) {
339
+ $parent_order = WCX::get_order( $parent_order_id );
340
+ $payment_method_title = WCX_Order::get_prop( $parent_order, 'payment_method_title', 'view' );
341
+ $payment_method = __( $payment_method_title, 'woocommerce' );
342
+ } else {
343
+ $payment_method_title = WCX_Order::get_prop( WPO_WCPDF()->export->order, 'payment_method_title', 'view' );
344
+ }
345
+
346
+ $payment_method = __( $payment_method_title, 'woocommerce' );
347
+
348
+ return apply_filters( 'wpo_wcpdf_payment_method', $payment_method );
349
+ }
350
+ public function payment_method() {
351
+ echo $this->get_payment_method();
352
+ }
353
+
354
+ /**
355
+ * Return/Show shipping method
356
+ */
357
+ public function get_shipping_method() {
358
+ $shipping_method_label = __( 'Shipping method', 'wpo_wcpdf' );
359
+ return apply_filters( 'wpo_wcpdf_shipping_method', __( WPO_WCPDF()->export->order->get_shipping_method(), 'woocommerce' ) );
360
+ }
361
+ public function shipping_method() {
362
+ echo $this->get_shipping_method();
363
+ }
364
+
365
+ /**
366
+ * Return/Show order number
367
+ */
368
+ public function get_order_number() {
369
+ $order_id = WCX_Order::get_id( WPO_WCPDF()->export->order );
370
+ // try parent first
371
+ if ( get_post_type( $order_id ) == 'shop_order_refund' && $parent_order_id = wp_get_post_parent_id( $order_id ) ) {
372
+ $parent_order = WCX::get_order( $parent_order_id );
373
+ $order_number = $parent_order->get_order_number();
374
+ } else {
375
+ $order_number = WPO_WCPDF()->export->order->get_order_number();
376
+ }
377
+
378
+ // Trim the hash to have a clean number but still
379
+ // support any filters that were applied before.
380
+ $order_number = ltrim($order_number, '#');
381
+ return apply_filters( 'wpo_wcpdf_order_number', $order_number);
382
+ }
383
+ public function order_number() {
384
+ echo $this->get_order_number();
385
+ }
386
+
387
+ /**
388
+ * Return/Show invoice number
389
+ */
390
+ public function get_invoice_number() {
391
+ $order_id = WCX_Order::get_id( WPO_WCPDF()->export->order );
392
+ // try parent first
393
+ if ( get_post_type( $order_id ) == 'shop_order_refund' && $parent_order_id = wp_get_post_parent_id( $order_id ) ) {
394
+ $invoice_number = WPO_WCPDF()->export->get_invoice_number( $parent_order_id );
395
+ } else {
396
+ $invoice_number = WPO_WCPDF()->export->get_invoice_number( $order_id );
397
+ }
398
+
399
+ return $invoice_number;
400
+ }
401
+ public function invoice_number() {
402
+ echo $this->get_invoice_number();
403
+ }
404
+
405
+ /**
406
+ * Return/Show the order date
407
+ */
408
+ public function get_order_date() {
409
+ $order_id = WCX_Order::get_id( WPO_WCPDF()->export->order );
410
+ // try parent first
411
+ if ( get_post_type( $order_id ) == 'shop_order_refund' && $parent_order_id = wp_get_post_parent_id( $order_id ) ) {
412
+ $parent_order = WCX::get_order( $parent_order_id );
413
+ $order_date = WCX_Order::get_prop( $parent_order, 'date_created' );
414
+ } else {
415
+ $order_date = WCX_Order::get_prop( WPO_WCPDF()->export->order, 'date_created' );
416
+ }
417
+
418
+ $date = $order_date->date_i18n( get_option( 'date_format' ) );
419
+ $mysql_date = $order_date->date( "Y-m-d H:i:s" );
420
+ return apply_filters( 'wpo_wcpdf_order_date', $date, $mysql_date );
421
+ }
422
+ public function order_date() {
423
+ echo $this->get_order_date();
424
+ }
425
+
426
+ /**
427
+ * Return/Show the invoice date
428
+ */
429
+ public function get_invoice_date() {
430
+ $invoice_date = WCX_Order::get_meta( WPO_WCPDF()->export->order, '_wcpdf_invoice_date', true );
431
+
432
+ // add invoice date if it doesn't exist
433
+ if ( empty($invoice_date) || !isset($invoice_date) ) {
434
+ $invoice_date = current_time('mysql');
435
+ WCX_Order::update_meta_data( WPO_WCPDF()->export->order, '_wcpdf_invoice_date', $invoice_date );
436
+ }
437
+
438
+ $formatted_invoice_date = date_i18n( get_option( 'date_format' ), strtotime( $invoice_date ) );
439
+
440
+ return apply_filters( 'wpo_wcpdf_invoice_date', $formatted_invoice_date, $invoice_date );
441
+ }
442
+ public function invoice_date() {
443
+ echo $this->get_invoice_date();
444
+ }
445
+
446
+ /**
447
+ * Return the order items
448
+ */
449
+ public function get_order_items() {
450
+ return apply_filters( 'wpo_wcpdf_order_items', WPO_WCPDF()->export->get_order_items() );
451
+ }
452
+
453
+ /**
454
+ * Return/show product attribute
455
+ */
456
+ public function get_product_attribute( $attribute_name, $product ) {
457
+ // first, check the text attributes
458
+ $attributes = $product->get_attributes();
459
+ $attribute_key = @wc_attribute_taxonomy_name( $attribute_name );
460
+ if (array_key_exists( sanitize_title( $attribute_name ), $attributes) ) {
461
+ $attribute = $product->get_attribute ( $attribute_name );
462
+ return $attribute;
463
+ } elseif (array_key_exists( sanitize_title( $attribute_key ), $attributes) ) {
464
+ $attribute = $product->get_attribute ( $attribute_key );
465
+ return $attribute;
466
+ }
467
+
468
+ // not a text attribute, try attribute taxonomy
469
+ $attribute_key = @wc_attribute_taxonomy_name( $attribute_name );
470
+ $product_id = WCX_Product::get_prop($product, 'id');
471
+ $product_terms = @wc_get_product_terms( $product_id, $attribute_key, array( 'fields' => 'names' ) );
472
+ // check if not empty, then display
473
+ if ( !empty($product_terms) ) {
474
+ $attribute = array_shift( $product_terms );
475
+ return $attribute;
476
+ } else {
477
+ // no attribute under this name
478
+ return false;
479
+ }
480
+ }
481
+ public function product_attribute( $attribute_name, $product ) {
482
+ echo $this->get_product_attribute( $attribute_name, $product );
483
+ }
484
+
485
+
486
+ /**
487
+ * Return the order totals listing
488
+ */
489
+ public function get_woocommerce_totals() {
490
+ // get totals and remove the semicolon
491
+ $totals = apply_filters( 'wpo_wcpdf_raw_order_totals', WPO_WCPDF()->export->order->get_order_item_totals(), WPO_WCPDF()->export->order );
492
+
493
+ // remove the colon for every label
494
+ foreach ( $totals as $key => $total ) {
495
+ $label = $total['label'];
496
+ $colon = strrpos( $label, ':' );
497
+ if( $colon !== false ) {
498
+ $label = substr_replace( $label, '', $colon, 1 );
499
+ }
500
+ $totals[$key]['label'] = $label;
501
+ }
502
+
503
+ // WC2.4 fix order_total for refunded orders
504
+ if ( version_compare( WOOCOMMERCE_VERSION, '2.4', '>=' ) && isset($totals['order_total']) ) {
505
+ $tax_display = WCX_Order::get_prop( WPO_WCPDF()->export->order, 'tax_display_cart' );
506
+ $totals['order_total']['value'] = wc_price( WPO_WCPDF()->export->order->get_total(), array( 'currency' => WCX_Order::get_prop( WPO_WCPDF()->export->order, 'currency' ) ) );
507
+ $order_total = WPO_WCPDF()->export->order->get_total();
508
+ $tax_string = '';
509
+
510
+ // Tax for inclusive prices
511
+ if ( wc_tax_enabled() && 'incl' == $tax_display ) {
512
+ $tax_string_array = array();
513
+
514
+ if ( 'itemized' == get_option( 'woocommerce_tax_total_display' ) ) {
515
+ foreach ( WPO_WCPDF()->export->order->get_tax_totals() as $code => $tax ) {
516
+ $tax_amount = $tax->formatted_amount;
517
+ $tax_string_array[] = sprintf( '%s %s', $tax_amount, $tax->label );
518
+ }
519
+ } else {
520
+ $tax_string_array[] = sprintf( '%s %s', wc_price( WPO_WCPDF()->export->order->get_total_tax() - WPO_WCPDF()->export->order->get_total_tax_refunded(), array( 'currency' => WPO_WCPDF()->export->order->get_order_currency() ) ), WC()->countries->tax_or_vat() );
521
+ }
522
+ if ( ! empty( $tax_string_array ) ) {
523
+ if ( version_compare( WOOCOMMERCE_VERSION, '2.6', '>=' ) ) {
524
+ $tax_string = ' ' . sprintf( __( '(includes %s)', 'woocommerce' ), implode( ', ', $tax_string_array ) );
525
+ } else {
526
+ // use old capitalized string
527
+ $tax_string = ' ' . sprintf( __( '(Includes %s)', 'woocommerce' ), implode( ', ', $tax_string_array ) );
528
+ }
529
+ }
530
+ }
531
+
532
+ $totals['order_total']['value'] .= $tax_string;
533
+ }
534
+
535
+ // remove refund lines (shouldn't be in invoice)
536
+ foreach ( $totals as $key => $total ) {
537
+ if ( strpos($key, 'refund_') !== false ) {
538
+ unset( $totals[$key] );
539
+ }
540
+ }
541
+
542
+ return apply_filters( 'wpo_wcpdf_woocommerce_totals', $totals, WPO_WCPDF()->export->order );
543
+ }
544
+
545
+ /**
546
+ * Return/show the order subtotal
547
+ */
548
+ public function get_order_subtotal( $tax = 'excl', $discount = 'incl' ) { // set $tax to 'incl' to include tax, same for $discount
549
+ //$compound = ($discount == 'incl')?true:false;
550
+ $subtotal = WPO_WCPDF()->export->order->get_subtotal_to_display( false, $tax );
551
+
552
+ $subtotal = ($pos = strpos($subtotal, ' <small')) ? substr($subtotal, 0, $pos) : $subtotal; //removing the 'excluding tax' text
553
+
554
+ $subtotal = array (
555
+ 'label' => __('Subtotal', 'wpo_wcpdf'),
556
+ 'value' => $subtotal,
557
+ );
558
+
559
+ return apply_filters( 'wpo_wcpdf_order_subtotal', $subtotal, $tax, $discount );
560
+ }
561
+ public function order_subtotal( $tax = 'excl', $discount = 'incl' ) {
562
+ $subtotal = $this->get_order_subtotal( $tax, $discount );
563
+ echo $subtotal['value'];
564
+ }
565
+
566
+ /**
567
+ * Return/show the order shipping costs
568
+ */
569
+ public function get_order_shipping( $tax = 'excl' ) { // set $tax to 'incl' to include tax
570
+ $shipping_cost = WCX_Order::get_prop( WPO_WCPDF()->export->order, 'shipping_total', 'view' );
571
+ $shipping_tax = WCX_Order::get_prop( WPO_WCPDF()->export->order, 'shipping_tax', 'view' );
572
+
573
+ if ($tax == 'excl' ) {
574
+ $formatted_shipping_cost = WPO_WCPDF()->export->wc_price( $shipping_cost );
575
+ } else {
576
+ $formatted_shipping_cost = WPO_WCPDF()->export->wc_price( $shipping_cost + $shipping_tax );
577
+ }
578
+
579
+ $shipping = array (
580
+ 'label' => __('Shipping', 'wpo_wcpdf'),
581
+ 'value' => $formatted_shipping_cost,
582
+ 'tax' => WPO_WCPDF()->export->wc_price( $shipping_tax ),
583
+ );
584
+ return apply_filters( 'wpo_wcpdf_order_shipping', $shipping, $tax );
585
+ }
586
+ public function order_shipping( $tax = 'excl' ) {
587
+ $shipping = $this->get_order_shipping( $tax );
588
+ echo $shipping['value'];
589
+ }
590
+
591
+ /**
592
+ * Return/show the total discount
593
+ */
594
+ public function get_order_discount( $type = 'total', $tax = 'incl' ) {
595
+ if ( $tax == 'incl' ) {
596
+ switch ($type) {
597
+ case 'cart':
598
+ // Cart Discount - pre-tax discounts. (deprecated in WC2.3)
599
+ $discount_value = WPO_WCPDF()->export->order->get_cart_discount();
600
+ break;
601
+ case 'order':
602
+ // Order Discount - post-tax discounts. (deprecated in WC2.3)
603
+ $discount_value = WPO_WCPDF()->export->order->get_order_discount();
604
+ break;
605
+ case 'total':
606
+ // Total Discount
607
+ if ( version_compare( WOOCOMMERCE_VERSION, '2.3' ) >= 0 ) {
608
+ $discount_value = WPO_WCPDF()->export->order->get_total_discount( false ); // $ex_tax = false
609
+ } else {
610
+ // WC2.2 and older: recalculate to include tax
611
+ $discount_value = 0;
612
+ $items = WPO_WCPDF()->export->order->get_items();;
613
+ if( sizeof( $items ) > 0 ) {
614
+ foreach( $items as $item ) {
615
+ $discount_value += ($item['line_subtotal'] + $item['line_subtotal_tax']) - ($item['line_total'] + $item['line_tax']);
616
+ }
617
+ }
618
+ }
619
+
620
+ break;
621
+ default:
622
+ // Total Discount - Cart & Order Discounts combined
623
+ $discount_value = WPO_WCPDF()->export->order->get_total_discount();
624
+ break;
625
+ }
626
+ } else { // calculate discount excluding tax
627
+ if ( version_compare( WOOCOMMERCE_VERSION, '2.3' ) >= 0 ) {
628
+ $discount_value = WPO_WCPDF()->export->order->get_total_discount( true ); // $ex_tax = true
629
+ } else {
630
+ // WC2.2 and older: recalculate to exclude tax
631
+ $discount_value = 0;
632
+
633
+ $items = WPO_WCPDF()->export->order->get_items();;
634
+ if( sizeof( $items ) > 0 ) {
635
+ foreach( $items as $item ) {
636
+ $discount_value += ($item['line_subtotal'] - $item['line_total']);
637
+ }
638
+ }
639
+ }
640
+ }
641
+
642
+ $discount = array (
643
+ 'label' => __('Discount', 'wpo_wcpdf'),
644
+ 'value' => WPO_WCPDF()->export->wc_price($discount_value),
645
+ 'raw_value' => $discount_value,
646
+ );
647
+
648
+ if ( round( $discount_value, 3 ) != 0 ) {
649
+ return apply_filters( 'wpo_wcpdf_order_discount', $discount, $type, $tax );
650
+ }
651
+ }
652
+ public function order_discount( $type = 'total', $tax = 'incl' ) {
653
+ $discount = $this->get_order_discount( $type, $tax );
654
+ echo $discount['value'];
655
+ }
656
+
657
+ /**
658
+ * Return the order fees
659
+ */
660
+ public function get_order_fees( $tax = 'excl' ) {
661
+ if ( $wcfees = WPO_WCPDF()->export->order->get_fees() ) {
662
+ foreach( $wcfees as $id => $fee ) {
663
+ if ($tax == 'excl' ) {
664
+ $fee_price = WPO_WCPDF()->export->wc_price( $fee['line_total'] );
665
+ } else {
666
+ $fee_price = WPO_WCPDF()->export->wc_price( $fee['line_total'] + $fee['line_tax'] );
667
+ }
668
+
669
+ $fees[ $id ] = array(
670
+ 'label' => $fee['name'],
671
+ 'value' => $fee_price,
672
+ 'line_total' => WPO_WCPDF()->export->wc_price($fee['line_total']),
673
+ 'line_tax' => WPO_WCPDF()->export->wc_price($fee['line_tax'])
674
+ );
675
+ }
676
+ return $fees;
677
+ }
678
+ }
679
+
680
+ /**
681
+ * Return the order taxes
682
+ */
683
+ public function get_order_taxes() {
684
+ $tax_label = __( 'VAT', 'wpo_wcpdf' ); // register alternate label translation
685
+ $tax_label = __( 'Tax rate', 'wpo_wcpdf' );
686
+ $tax_rate_ids = WPO_WCPDF()->export->get_tax_rate_ids();
687
+ if (WPO_WCPDF()->export->order->get_taxes()) {
688
+ foreach ( WPO_WCPDF()->export->order->get_taxes() as $key => $tax ) {
689
+ if ( WCX::is_wc_version_gte_3_0() ) {
690
+ $taxes[ $key ] = array(
691
+ 'label' => $tax->get_label(),
692
+ 'value' => WPO_WCPDF()->export->wc_price( $tax->get_tax_total() + $tax->get_shipping_tax_total() ),
693
+ 'rate_id' => $tax->get_rate_id(),
694
+ 'tax_amount' => $tax->get_tax_total(),
695
+ 'shipping_tax_amount' => $tax->get_shipping_tax_total(),
696
+ 'rate' => isset( $tax_rate_ids[ $tax->get_rate_id() ] ) ? ( (float) $tax_rate_ids[$tax->get_rate_id()]['tax_rate'] ) . ' %': '',
697
+ );
698
+ } else {
699
+ $taxes[ $key ] = array(
700
+ 'label' => isset( $tax[ 'label' ] ) ? $tax[ 'label' ] : $tax[ 'name' ],
701
+ 'value' => WPO_WCPDF()->export->wc_price( ( $tax[ 'tax_amount' ] + $tax[ 'shipping_tax_amount' ] ) ),
702
+ 'rate_id' => $tax['rate_id'],
703
+ 'tax_amount' => $tax['tax_amount'],
704
+ 'shipping_tax_amount' => $tax['shipping_tax_amount'],
705
+ 'rate' => isset( $tax_rate_ids[ $tax['rate_id'] ] ) ? ( (float) $tax_rate_ids[$tax['rate_id']]['tax_rate'] ) . ' %': '',
706
+ );
707
+ }
708
+
709
+ }
710
+
711
+ return apply_filters( 'wpo_wcpdf_order_taxes', $taxes );
712
+ }
713
+ }
714
+
715
+ /**
716
+ * Return/show the order grand total
717
+ */
718
+ public function get_order_grand_total( $tax = 'incl' ) {
719
+ if ( version_compare( WOOCOMMERCE_VERSION, '2.1' ) >= 0 ) {
720
+ // WC 2.1 or newer is used
721
+ $total_unformatted = WPO_WCPDF()->export->order->get_total();
722
+ } else {
723
+ // Backwards compatibility
724
+ $total_unformatted = WPO_WCPDF()->export->order->get_order_total();
725
+ }
726
+
727
+ if ($tax == 'excl' ) {
728
+ $total = WPO_WCPDF()->export->wc_price( $total_unformatted - WPO_WCPDF()->export->order->get_total_tax() );
729
+ $label = __( 'Total ex. VAT', 'wpo_wcpdf' );
730
+ } else {
731
+ $total = WPO_WCPDF()->export->wc_price( ( $total_unformatted ) );
732
+ $label = __( 'Total', 'wpo_wcpdf' );
733
+ }
734
+
735
+ $grand_total = array(
736
+ 'label' => $label,
737
+ 'value' => $total,
738
+ );
739
+
740
+ return apply_filters( 'wpo_wcpdf_order_grand_total', $grand_total, $tax );
741
+ }
742
+ public function order_grand_total( $tax = 'incl' ) {
743
+ $grand_total = $this->get_order_grand_total( $tax );
744
+ echo $grand_total['value'];
745
+ }
746
+
747
+
748
+ /**
749
+ * Return/Show shipping notes
750
+ */
751
+ public function get_shipping_notes() {
752
+ $shipping_notes = wpautop( wptexturize( WCX_Order::get_prop( WPO_WCPDF()->export->order, 'customer_note', 'view' ) ) );
753
+ return apply_filters( 'wpo_wcpdf_shipping_notes', $shipping_notes );
754
+ }
755
+ public function shipping_notes() {
756
+ echo $this->get_shipping_notes();
757
+ }
758
+
759
+
760
+ /**
761
+ * Return/Show shop/company footer imprint, copyright etc.
762
+ */
763
+ public function get_footer() {
764
+ if (isset(WPO_WCPDF()->settings->template_settings['footer'])) {
765
+ $footer = wpautop( wptexturize( WPO_WCPDF()->settings->template_settings[ 'footer' ] ) );
766
+ return apply_filters( 'wpo_wcpdf_footer', $footer );
767
+ }
768
+ }
769
+ public function footer() {
770
+ echo $this->get_footer();
771
+ }
772
+
773
+ /**
774
+ * Return/Show Extra field 1
775
+ */
776
+ public function get_extra_1() {
777
+ if (isset(WPO_WCPDF()->settings->template_settings['extra_1'])) {
778
+ $extra_1 = nl2br( wptexturize( WPO_WCPDF()->settings->template_settings[ 'extra_1' ] ) );
779
+ return apply_filters( 'wpo_wcpdf_extra_1', $extra_1 );
780
+ }
781
+ }
782
+ public function extra_1() {
783
+ echo $this->get_extra_1();
784
+ }
785
+
786
+ /**
787
+ * Return/Show Extra field 2
788
+ */
789
+ public function get_extra_2() {
790
+ if (isset(WPO_WCPDF()->settings->template_settings['extra_2'])) {
791
+ $extra_2 = nl2br( wptexturize( WPO_WCPDF()->settings->template_settings[ 'extra_2' ] ) );
792
+ return apply_filters( 'wpo_wcpdf_extra_2', $extra_2 );
793
+ }
794
+ }
795
+ public function extra_2() {
796
+ echo $this->get_extra_2();
797
+ }
798
+
799
+ /**
800
+ * Return/Show Extra field 3
801
+ */
802
+ public function get_extra_3() {
803
+ if (isset(WPO_WCPDF()->settings->template_settings['extra_3'])) {
804
+ $extra_3 = nl2br( wptexturize( WPO_WCPDF()->settings->template_settings[ 'extra_3' ] ) );
805
+ return apply_filters( 'wpo_wcpdf_extra_3', $extra_3 );
806
+ }
807
+ }
808
+ public function extra_3() {
809
+ echo $this->get_extra_3();
810
+ }
811
+ }
812
+
813
+ endif; // class_exists
includes/class-wcpdf-settings.php CHANGED
@@ -1,4 +1,5 @@
1
  <?php
 
2
 
3
  /**
4
  * Settings class
1
  <?php
2
+ defined( 'ABSPATH' ) or exit;
3
 
4
  /**
5
  * Settings class
includes/class-wcpdf-writepanels.php CHANGED
@@ -1,4 +1,9 @@
1
  <?php
 
 
 
 
 
2
 
3
  /**
4
  * Writepanel class
@@ -109,18 +114,18 @@ if ( !class_exists( 'WooCommerce_PDF_Invoices_Writepanels' ) ) {
109
  */
110
  public function add_listing_actions( $order ) {
111
  // do not show buttons for trashed orders
112
- if ( $order->status == 'trash' ) {
113
  return;
114
  }
115
 
116
  $listing_actions = array(
117
  'invoice' => array (
118
- 'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=generate_wpo_wcpdf&template_type=invoice&order_ids=' . $order->id ), 'generate_wpo_wcpdf' ),
119
  'img' => WooCommerce_PDF_Invoices::$plugin_url . 'images/invoice.png',
120
  'alt' => __( 'PDF Invoice', 'wpo_wcpdf' ),
121
  ),
122
  'packing-slip' => array (
123
- 'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=generate_wpo_wcpdf&template_type=packing-slip&order_ids=' . $order->id ), 'generate_wpo_wcpdf' ),
124
  'img' => WooCommerce_PDF_Invoices::$plugin_url . 'images/packing-slip.png',
125
  'alt' => __( 'PDF Packing Slip', 'wpo_wcpdf' ),
126
  ),
@@ -162,12 +167,12 @@ if ( !class_exists( 'WooCommerce_PDF_Invoices_Writepanels' ) ) {
162
  global $post, $the_order, $wpo_wcpdf;
163
 
164
  if ( $column == 'pdf_invoice_number' ) {
165
- if ( empty( $the_order ) || $the_order->id != $post->ID ) {
166
- $order = new WC_Order( $post->ID );
167
- echo $wpo_wcpdf->export->get_invoice_number( $order->id );
168
  do_action( 'wcpdf_invoice_number_column_end', $order );
169
  } else {
170
- echo $wpo_wcpdf->export->get_invoice_number( $the_order->id );
171
  do_action( 'wcpdf_invoice_number_column_end', $the_order );
172
  }
173
  }
@@ -177,13 +182,13 @@ if ( !class_exists( 'WooCommerce_PDF_Invoices_Writepanels' ) ) {
177
  * Display download link on My Account page
178
  */
179
  public function my_account_pdf_link( $actions, $order ) {
180
- $pdf_url = wp_nonce_url( admin_url( 'admin-ajax.php?action=generate_wpo_wcpdf&template_type=invoice&order_ids=' . $order->id . '&my-account'), 'generate_wpo_wcpdf' );
181
 
182
  // check my account button settings
183
  if (isset($this->general_settings['my_account_buttons'])) {
184
  switch ($this->general_settings['my_account_buttons']) {
185
  case 'available':
186
- $invoice_allowed = get_post_meta($order->id,'_wcpdf_invoice_exists',true);
187
  break;
188
  case 'always':
189
  $invoice_allowed = true;
@@ -192,7 +197,7 @@ if ( !class_exists( 'WooCommerce_PDF_Invoices_Writepanels' ) ) {
192
  $invoice_allowed = false;
193
  break;
194
  case 'custom':
195
- if ( isset( $this->general_settings['my_account_restrict'] ) && in_array( $order->status, array_keys( $this->general_settings['my_account_restrict'] ) ) ) {
196
  $invoice_allowed = true;
197
  } else {
198
  $invoice_allowed = false;
@@ -201,11 +206,11 @@ if ( !class_exists( 'WooCommerce_PDF_Invoices_Writepanels' ) ) {
201
  }
202
  } else {
203
  // backwards compatibility
204
- $invoice_allowed = get_post_meta($order->id,'_wcpdf_invoice_exists',true);
205
  }
206
 
207
  // Check if invoice has been created already or if status allows download (filter your own array of allowed statuses)
208
- if ( $invoice_allowed || in_array($order->status, apply_filters( 'wpo_wcpdf_myaccount_allowed_order_statuses', array() ) ) ) {
209
  $actions['invoice'] = array(
210
  'url' => $pdf_url,
211
  'name' => apply_filters( 'wpo_wcpdf_myaccount_button_text', __( 'Download invoice (PDF)', 'wpo_wcpdf' ) )
@@ -276,9 +281,10 @@ if ( !class_exists( 'WooCommerce_PDF_Invoices_Writepanels' ) ) {
276
  * Add metabox for invoice number & date
277
  */
278
  public function data_input_box_content ( $post ) {
279
- $invoice_exists = get_post_meta( $post->ID, '_wcpdf_invoice_exists', true );
280
- $invoice_number = get_post_meta($post->ID,'_wcpdf_invoice_number',true);
281
- $invoice_date = get_post_meta($post->ID,'_wcpdf_invoice_date',true);
 
282
 
283
  do_action( 'wpo_wcpdf_meta_box_start', $post->ID );
284
 
@@ -329,31 +335,34 @@ if ( !class_exists( 'WooCommerce_PDF_Invoices_Writepanels' ) ) {
329
  * Save invoice number
330
  */
331
  public function save_invoice_number_date($post_id) {
332
- global $post_type;
 
333
  if( $post_type == 'shop_order' ) {
 
334
  if ( isset($_POST['_wcpdf_invoice_number']) ) {
335
- update_post_meta( $post_id, '_wcpdf_invoice_number', stripslashes( $_POST['_wcpdf_invoice_number'] ));
336
- update_post_meta( $post_id, '_wcpdf_invoice_exists', 1 );
 
337
  }
338
 
339
  if ( isset($_POST['wcpdf_invoice_date']) ) {
340
  if ( empty($_POST['wcpdf_invoice_date']) ) {
341
- delete_post_meta( $post_id, '_wcpdf_invoice_date' );
342
  } else {
343
  $invoice_date = strtotime( $_POST['wcpdf_invoice_date'] . ' ' . (int) $_POST['wcpdf_invoice_date_hour'] . ':' . (int) $_POST['wcpdf_invoice_date_minute'] . ':00' );
344
  $invoice_date = date_i18n( 'Y-m-d H:i:s', $invoice_date );
345
- update_post_meta( $post_id, '_wcpdf_invoice_date', $invoice_date );
346
- update_post_meta( $post_id, '_wcpdf_invoice_exists', 1 );
347
  }
348
  }
349
 
350
  if (empty($_POST['wcpdf_invoice_date']) && isset($_POST['_wcpdf_invoice_number'])) {
351
  $invoice_date = date_i18n( 'Y-m-d H:i:s', time() );
352
- update_post_meta( $post_id, '_wcpdf_invoice_date', $invoice_date );
353
  }
354
 
355
  if ( empty($_POST['wcpdf_invoice_date']) && empty($_POST['_wcpdf_invoice_number'])) {
356
- delete_post_meta( $post_id, '_wcpdf_invoice_exists' );
357
  }
358
  }
359
  }
1
  <?php
2
+ use WPO\WC\PDF_Invoices\Compatibility\WC_Core as WCX;
3
+ use WPO\WC\PDF_Invoices\Compatibility\Order as WCX_Order;
4
+ use WPO\WC\PDF_Invoices\Compatibility\Product as WCX_Product;
5
+
6
+ defined( 'ABSPATH' ) or exit;
7
 
8
  /**
9
  * Writepanel class
114
  */
115
  public function add_listing_actions( $order ) {
116
  // do not show buttons for trashed orders
117
+ if ( WCX_Order::get_status( $order ) == 'trash' ) {
118
  return;
119
  }
120
 
121
  $listing_actions = array(
122
  'invoice' => array (
123
+ 'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=generate_wpo_wcpdf&template_type=invoice&order_ids=' . WCX_Order::get_id( $order ) ), 'generate_wpo_wcpdf' ),
124
  'img' => WooCommerce_PDF_Invoices::$plugin_url . 'images/invoice.png',
125
  'alt' => __( 'PDF Invoice', 'wpo_wcpdf' ),
126
  ),
127
  'packing-slip' => array (
128
+ 'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=generate_wpo_wcpdf&template_type=packing-slip&order_ids=' . WCX_Order::get_id( $order ) ), 'generate_wpo_wcpdf' ),
129
  'img' => WooCommerce_PDF_Invoices::$plugin_url . 'images/packing-slip.png',
130
  'alt' => __( 'PDF Packing Slip', 'wpo_wcpdf' ),
131
  ),
167
  global $post, $the_order, $wpo_wcpdf;
168
 
169
  if ( $column == 'pdf_invoice_number' ) {
170
+ if ( empty( $the_order ) || WCX_Order::get_id( $the_order ) != $post->ID ) {
171
+ $order = WCX::get_order( $post->ID );
172
+ echo $wpo_wcpdf->export->get_invoice_number( WCX_Order::get_id( $order ) );
173
  do_action( 'wcpdf_invoice_number_column_end', $order );
174
  } else {
175
+ echo $wpo_wcpdf->export->get_invoice_number( WCX_Order::get_id( $the_order ) );
176
  do_action( 'wcpdf_invoice_number_column_end', $the_order );
177
  }
178
  }
182
  * Display download link on My Account page
183
  */
184
  public function my_account_pdf_link( $actions, $order ) {
185
+ $pdf_url = wp_nonce_url( admin_url( 'admin-ajax.php?action=generate_wpo_wcpdf&template_type=invoice&order_ids=' . WCX_Order::get_id( $order ) . '&my-account'), 'generate_wpo_wcpdf' );
186
 
187
  // check my account button settings
188
  if (isset($this->general_settings['my_account_buttons'])) {
189
  switch ($this->general_settings['my_account_buttons']) {
190
  case 'available':
191
+ $invoice_allowed = WCX_Order::get_meta( $order, 'wcpdf_invoice_exists', true );
192
  break;
193
  case 'always':
194
  $invoice_allowed = true;
197
  $invoice_allowed = false;
198
  break;
199
  case 'custom':
200
+ if ( isset( $this->general_settings['my_account_restrict'] ) && in_array( WCX_Order::get_status( $order ), array_keys( $this->general_settings['my_account_restrict'] ) ) ) {
201
  $invoice_allowed = true;
202
  } else {
203
  $invoice_allowed = false;
206
  }
207
  } else {
208
  // backwards compatibility
209
+ $invoice_allowed = WCX_Order::get_meta( $order, 'wcpdf_invoice_exists', true );
210
  }
211
 
212
  // Check if invoice has been created already or if status allows download (filter your own array of allowed statuses)
213
+ if ( $invoice_allowed || in_array(WCX_Order::get_status( $order ), apply_filters( 'wpo_wcpdf_myaccount_allowed_order_statuses', array() ) ) ) {
214
  $actions['invoice'] = array(
215
  'url' => $pdf_url,
216
  'name' => apply_filters( 'wpo_wcpdf_myaccount_button_text', __( 'Download invoice (PDF)', 'wpo_wcpdf' ) )
281
  * Add metabox for invoice number & date
282
  */
283
  public function data_input_box_content ( $post ) {
284
+ $order = WCX::get_order( $post->ID );
285
+ $invoice_exists = WCX_Order::get_meta( $order, '_wcpdf_invoice_exists', true );
286
+ $invoice_number = WCX_Order::get_meta( $order, '_wcpdf_invoice_number', true );
287
+ $invoice_date = WCX_Order::get_meta( $order, '_wcpdf_invoice_date', true );
288
 
289
  do_action( 'wpo_wcpdf_meta_box_start', $post->ID );
290
 
335
  * Save invoice number
336
  */
337
  public function save_invoice_number_date($post_id) {
338
+ global $wpo_wcpdf;
339
+ $post_type = get_post_type( $post_id );
340
  if( $post_type == 'shop_order' ) {
341
+ $order = WCX::get_order( $post_id );
342
  if ( isset($_POST['_wcpdf_invoice_number']) ) {
343
+ WCX_Order::update_meta_data( $order, '_wcpdf_invoice_number', stripslashes( $_POST['_wcpdf_invoice_number'] ) );
344
+ WCX_Order::update_meta_data( $order, '_wcpdf_formatted_invoice_number', $wpo_wcpdf->export->get_invoice_number( $post_id ) );
345
+ WCX_Order::update_meta_data( $order, '_wcpdf_invoice_exists', 1 );
346
  }
347
 
348
  if ( isset($_POST['wcpdf_invoice_date']) ) {
349
  if ( empty($_POST['wcpdf_invoice_date']) ) {
350
+ WCX_Order::delete_meta_data( $order, '_wcpdf_invoice_date' );
351
  } else {
352
  $invoice_date = strtotime( $_POST['wcpdf_invoice_date'] . ' ' . (int) $_POST['wcpdf_invoice_date_hour'] . ':' . (int) $_POST['wcpdf_invoice_date_minute'] . ':00' );
353
  $invoice_date = date_i18n( 'Y-m-d H:i:s', $invoice_date );
354
+ WCX_Order::update_meta_data( $order, '_wcpdf_invoice_date', $invoice_date );
355
+ WCX_Order::update_meta_data( $order, '_wcpdf_invoice_exists', 1 );
356
  }
357
  }
358
 
359
  if (empty($_POST['wcpdf_invoice_date']) && isset($_POST['_wcpdf_invoice_number'])) {
360
  $invoice_date = date_i18n( 'Y-m-d H:i:s', time() );
361
+ WCX_Order::update_meta_data( $order, '_wcpdf_invoice_date', $invoice_date );
362
  }
363
 
364
  if ( empty($_POST['wcpdf_invoice_date']) && empty($_POST['_wcpdf_invoice_number'])) {
365
+ WCX_Order::delete_meta_data( $order, '_wcpdf_invoice_exists' );
366
  }
367
  }
368
  }
includes/compatibility/abstract-wc-data-compatibility.php ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Derived from SkyVerge WooCommerce Plugin Framework https://github.com/skyverge/wc-plugin-framework/
4
+ */
5
+
6
+ namespace WPO\WC\PDF_Invoices\Compatibility;
7
+
8
+ defined( 'ABSPATH' ) or exit;
9
+
10
+ if ( ! class_exists( '\\WPO\\WC\\PDF_Invoices\\Compatibility\\Data' ) ) :
11
+
12
+ /**
13
+ * WooCommerce data compatibility class.
14
+ *
15
+ * @since 4.6.0-dev
16
+ */
17
+ abstract class Data {
18
+
19
+ /**
20
+ * Creates aliases for add_meta_data, update_meta_data and delete_meta_data without the _data suffix
21
+ *
22
+ * @param string $name static function name
23
+ * @param array $arguments function arguments
24
+ */
25
+ public static function __callStatic( $name, $arguments ) {
26
+ if ( substr( $name, -strlen('_meta') ) == '_meta' && method_exists( __CLASS__, $name.'_data' ) ) {
27
+ call_user_func_array( array( __CLASS__, $name.'_data' ), $arguments );
28
+ }
29
+ }
30
+
31
+
32
+ /**
33
+ * Gets an object property.
34
+ *
35
+ * @since 4.6.0-dev
36
+ * @param \WC_Data $object the data object, likely \WC_Order or \WC_Product
37
+ * @param string $prop the property name
38
+ * @param string $context if 'view' then the value will be filtered
39
+ * @param array $compat_props Compatibility properties.
40
+ * @return mixed
41
+ */
42
+ public static function get_prop( $object, $prop, $context = 'edit', $compat_props = array() ) {
43
+
44
+ $value = '';
45
+
46
+ if ( WC_Core::is_wc_version_gte_3_0() ) {
47
+
48
+ if ( is_callable( array( $object, "get_{$prop}" ) ) ) {
49
+ $value = $object->{"get_{$prop}"}( $context );
50
+ }
51
+
52
+ } else {
53
+
54
+ // backport the property name
55
+ if ( isset( $compat_props[ $prop ] ) ) {
56
+ $prop = $compat_props[ $prop ];
57
+ }
58
+
59
+ // if this is the 'view' context and there is an accessor method, use it
60
+ if ( is_callable( array( $object, "get_{$prop}" ) ) && 'view' === $context ) {
61
+ $value = $object->{"get_{$prop}"}();
62
+ } else {
63
+ $value = $object->$prop;
64
+ }
65
+ }
66
+
67
+ return $value;
68
+ }
69
+
70
+
71
+ /**
72
+ * Sets an object's properties.
73
+ *
74
+ * Note that this does not save any data to the database.
75
+ *
76
+ * @since 4.6.0-dev
77
+ * @param \WC_Data $object the data object, likely \WC_Order or \WC_Product
78
+ * @param array $props the new properties as $key => $value
79
+ * @param array $compat_props Compatibility properties.
80
+ * @return \WC_Data
81
+ */
82
+ public static function set_props( $object, $props, $compat_props = array() ) {
83
+
84
+ if ( WC_Core::is_wc_version_gte_3_0() ) {
85
+
86
+ $object->set_props( $props );
87
+
88
+ } else {
89
+
90
+ foreach ( $props as $prop => $value ) {
91
+
92
+ if ( isset( $compat_props[ $prop ] ) ) {
93
+ $prop = $compat_props[ $prop ];
94
+ }
95
+
96
+ $object->$prop = $value;
97
+ }
98
+ }
99
+
100
+ return $object;
101
+ }
102
+
103
+
104
+ /**
105
+ * Gets an object's stored meta value.
106
+ *
107
+ * @since 4.6.0-dev
108
+ * @param \WC_Data $object the data object, likely \WC_Order or \WC_Product
109
+ * @param string $key the meta key
110
+ * @param bool $single whether to get the meta as a single item. Defaults to `true`
111
+ * @param string $context if 'view' then the value will be filtered
112
+ * @return mixed
113
+ */
114
+ public static function get_meta( $object, $key = '', $single = true, $context = 'edit' ) {
115
+
116
+ if ( WC_Core::is_wc_version_gte_3_0() ) {
117
+ $value = $object->get_meta( $key, $single, $context );
118
+ } else {
119
+ $object_id = is_callable( array( $object, 'get_id' ) ) ? $object->get_id() : $object->id;
120
+ $value = get_post_meta( $object_id, $key, $single );
121
+ }
122
+
123
+ return $value;
124
+ }
125
+
126
+
127
+ /**
128
+ * Stores an object meta value.
129
+ *
130
+ * @since 4.6.0-dev
131
+ * @param \WC_Data $object the data object, likely \WC_Order or \WC_Product
132
+ * @param string $key the meta key
133
+ * @param string $value the meta value
134
+ * @param string $meta_id Optional. The specific meta ID to update
135
+ * @param bool $unique Optional. Whether the meta should be unique.
136
+ */
137
+ public static function add_meta_data( $object, $key, $value, $unique = false ) {
138
+
139
+ if ( WC_Core::is_wc_version_gte_3_0() ) {
140
+
141
+ $object->add_meta_data( $key, $value, $unique );
142
+
143
+ $object->save_meta_data();
144
+
145
+ } else {
146
+
147
+ $object_id = is_callable( array( $object, 'get_id' ) ) ? $object->get_id() : $object->id;
148
+ add_post_meta( $object_id, $key, $value, $unique );
149
+ }
150
+ }
151
+
152
+
153
+ /**
154
+ * Updates an object's stored meta value.
155
+ *
156
+ * @since 4.6.0-dev
157
+ * @param \WC_Data $object the data object, likely \WC_Order or \WC_Product
158
+ * @param string $key the meta key
159
+ * @param string $value the meta value
160
+ * @param int|strint $meta_id Optional. The specific meta ID to update
161
+ */
162
+ public static function update_meta_data( $object, $key, $value, $meta_id = '' ) {
163
+
164
+ if ( WC_Core::is_wc_version_gte_3_0() ) {
165
+
166
+ $object->update_meta_data( $key, $value, $meta_id );
167
+
168
+ $object->save_meta_data();
169
+
170
+ } else {
171
+
172
+ $object_id = is_callable( array( $object, 'get_id' ) ) ? $object->get_id() : $object->id;
173
+ update_post_meta( $object_id, $key, $value );
174
+ }
175
+ }
176
+
177
+
178
+ /**
179
+ * Deletes an object's stored meta value.
180
+ *
181
+ * @since 4.6.0-dev
182
+ * @param \WC_Data $object the data object, likely \WC_Order or \WC_Product
183
+ * @param string $key the meta key
184
+ */
185
+ public static function delete_meta_data( $object, $key ) {
186
+
187
+ if ( WC_Core::is_wc_version_gte_3_0() ) {
188
+
189
+ $object->delete_meta_data( $key );
190
+
191
+ $object->save_meta_data();
192
+
193
+ } else {
194
+
195
+ $object_id = is_callable( array( $object, 'get_id' ) ) ? $object->get_id() : $object->id;
196
+ delete_post_meta( $object_id, $key );
197
+ }
198
+ }
199
+
200
+
201
+ }
202
+
203
+
204
+ endif; // Class exists check
includes/compatibility/class-wc-core-compatibility.php ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Derived from SkyVerge WooCommerce Plugin Framework https://github.com/skyverge/wc-plugin-framework/
4
+ */
5
+
6
+ namespace WPO\WC\PDF_Invoices\Compatibility;
7
+
8
+ defined( 'ABSPATH' ) or exit;
9
+
10
+ if ( ! class_exists( '\\WPO\\WC\\PDF_Invoices\\Compatibility\\WC_Core' ) ) :
11
+
12
+ /**
13
+ * WooCommerce Compatibility Utility Class
14
+ *
15
+ * The unfortunate purpose of this class is to provide a single point of
16
+ * compatibility functions for dealing with supporting multiple versions
17
+ * of WooCommerce and various extensions.
18
+ *
19
+ * The expected procedure is to remove methods from this class, using the
20
+ * latest ones directly in code, as support for older versions of WooCommerce
21
+ * are dropped.
22
+ *
23
+ * Current Compatibility
24
+ * + Core 2.5.5 - 3.0.x
25
+ *
26
+ *
27
+ * @since 2.0.0
28
+ */
29
+ class WC_Core {
30
+
31
+ /**
32
+ * Backports wc_get_order() to pre-2.2.0
33
+ *
34
+ * @since 4.3.0
35
+ * @return \WC_Order $order order object
36
+ */
37
+ public static function get_order( $order_id ) {
38
+
39
+ if ( function_exists( 'wc_get_order' ) ) {
40
+
41
+ return wc_get_order( $order_id );
42
+
43
+ } else {
44
+
45
+ return new \WC_Order( $order_id );
46
+ }
47
+ }
48
+
49
+
50
+ /**
51
+ * Backports wc_checkout_is_https() to 2.4.x
52
+ *
53
+ * @since 4.3.0
54
+ * @return bool
55
+ */
56
+ public static function wc_checkout_is_https() {
57
+
58
+ if ( self::is_wc_version_gte_2_5() ) {
59
+
60
+ return wc_checkout_is_https();
61
+
62
+ } else {
63
+
64
+ return wc_site_is_https() || 'yes' === get_option( 'woocommerce_force_ssl_checkout' ) || class_exists( 'WordPressHTTPS' ) || strstr( wc_get_page_permalink( 'checkout' ), 'https:' );
65
+ }
66
+ }
67
+
68
+
69
+ /**
70
+ * Backports wc_help_tip() to WC 2.4.x
71
+ *
72
+ * @link https://github.com/woothemes/woocommerce/pull/9417
73
+ *
74
+ * @since 4.2.0
75
+ * @param string $tip help tip content, HTML allowed if $has_html is true
76
+ * @param bool $has_html false by default, true to indicate tip content has HTML
77
+ * @return string help tip HTML, a <span> in WC 2.5, <img> in WC 2.4
78
+ */
79
+ public static function wc_help_tip( $tip, $has_html = false ) {
80
+
81
+ if ( self::is_wc_version_gte_2_5() ) {
82
+
83
+ return wc_help_tip( $tip, $has_html );
84
+
85
+ } else {
86
+
87
+ $tip = $has_html ? wc_sanitize_tooltip( $tip ) : esc_attr( $tip );
88
+
89
+ return sprintf( '<img class="help_tip" data-tip="%1$s" src="%2$s" height="16" width="16" />', $tip, esc_url( WC()->plugin_url() ) . '/assets/images/help.png' );
90
+ }
91
+ }
92
+
93
+
94
+ /**
95
+ * Helper method to get the version of the currently installed WooCommerce
96
+ *
97
+ * @since 3.0.0
98
+ * @return string woocommerce version number or null
99
+ */
100
+ protected static function get_wc_version() {
101
+
102
+ return defined( 'WC_VERSION' ) && WC_VERSION ? WC_VERSION : null;
103
+ }
104
+
105
+
106
+ /**
107
+ * Determines if the installed version of WooCommerce is 2.2.0 or greater.
108
+ *
109
+ * @since 4.2.0
110
+ * @return bool
111
+ */
112
+ public static function is_wc_version_gte_2_2() {
113
+ return self::get_wc_version() && version_compare( self::get_wc_version(), '2.2', '>=' );
114
+ }
115
+
116
+
117
+ /**
118
+ * Determines if the installed version of WooCommerce is less than 2.2.0
119
+ *
120
+ * @since 4.2.0
121
+ * @return bool
122
+ */
123
+ public static function is_wc_version_lt_2_2() {
124
+ return self::get_wc_version() && version_compare( self::get_wc_version(), '2.2', '<' );
125
+ }
126
+
127
+
128
+ /**
129
+ * Determines if the installed version of WooCommerce is 2.5.0 or greater.
130
+ *
131
+ * @since 4.2.0
132
+ * @return bool
133
+ */
134
+ public static function is_wc_version_gte_2_5() {
135
+ return self::get_wc_version() && version_compare( self::get_wc_version(), '2.5', '>=' );
136
+ }
137
+
138
+
139
+ /**
140
+ * Determines if the installed version of WooCommerce is less than 2.5.0
141
+ *
142
+ * @since 4.2.0
143
+ * @return bool
144
+ */
145
+ public static function is_wc_version_lt_2_5() {
146
+ return self::get_wc_version() && version_compare( self::get_wc_version(), '2.5', '<' );
147
+ }
148
+
149
+
150
+ /**
151
+ * Determines if the installed version of WooCommerce is 2.6.0 or greater.
152
+ *
153
+ * @since 4.4.0
154
+ * @return bool
155
+ */
156
+ public static function is_wc_version_gte_2_6() {
157
+ return self::get_wc_version() && version_compare( self::get_wc_version(), '2.6', '>=' );
158
+ }
159
+
160
+
161
+ /**
162
+ * Determines if the installed version of WooCommerce is less than 2.6.0
163
+ *
164
+ * @since 4.4.0
165
+ * @return bool
166
+ */
167
+ public static function is_wc_version_lt_2_6() {
168
+ return self::get_wc_version() && version_compare( self::get_wc_version(), '2.6', '<' );
169
+ }
170
+
171
+
172
+ /**
173
+ * Determines if the installed version of WooCommerce is 3.0.0 or greater.
174
+ *
175
+ * @since 4.6.0-dev
176
+ * @return bool
177
+ */
178
+ public static function is_wc_version_gte_3_0() {
179
+ return self::get_wc_version() && version_compare( self::get_wc_version(), '3.0', '>=' );
180
+ }
181
+
182
+
183
+ /**
184
+ * Determines if the installed version of WooCommerce is less than 3.0.0
185
+ *
186
+ * @since 4.6.0-dev
187
+ * @return bool
188
+ */
189
+ public static function is_wc_version_lt_3_0() {
190
+ return self::get_wc_version() && version_compare( self::get_wc_version(), '3.0', '<' );
191
+ }
192
+
193
+ /**
194
+ * Returns true if the installed version of WooCommerce is greater than $version
195
+ *
196
+ * @since 2.0.0
197
+ * @param string $version the version to compare
198
+ * @return boolean true if the installed version of WooCommerce is > $version
199
+ */
200
+ public static function is_wc_version_gt( $version ) {
201
+ return self::get_wc_version() && version_compare( self::get_wc_version(), $version, '>' );
202
+ }
203
+
204
+
205
+ /** WordPress core ******************************************************/
206
+
207
+
208
+ /**
209
+ * Normalizes a WooCommerce page screen ID.
210
+ *
211
+ * Needed because WordPress uses a menu title (which is translatable), not slug, to generate screen ID.
212
+ * See details in: https://core.trac.wordpress.org/ticket/21454
213
+ * TODO: Add WP version check when https://core.trac.wordpress.org/ticket/18857 is addressed {BR 2016-12-12}
214
+ *
215
+ * @since 4.6.0-dev
216
+ * @param string $slug The slug for the screen ID to normalize (minus `woocommerce_page_`).
217
+ * @return string Normalized screen ID.
218
+ */
219
+ public static function normalize_wc_screen_id( $slug = 'wc-settings' ) {
220
+
221
+ // The textdomain usage is intentional here, we need to match the menu title.
222
+ $prefix = sanitize_title( __( 'WooCommerce', 'woocommerce' ) );
223
+
224
+ return $prefix . '_page_' . $slug;
225
+ }
226
+
227
+
228
+ }
229
+
230
+
231
+ endif; // Class exists check
includes/compatibility/class-wc-date-compatibility.php ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copy of WC3.0 WC_DateTime class
4
+ */
5
+
6
+ namespace WPO\WC\PDF_Invoices\Compatibility;
7
+
8
+ defined( 'ABSPATH' ) or exit;
9
+
10
+ if ( ! class_exists( '\\WPO\\WC\\PDF_Invoices\\Compatibility\\WC_DateTime' ) ) :
11
+
12
+
13
+ /**
14
+ * WC Wrapper for PHP DateTime.
15
+ *
16
+ * @class WC_DateTime
17
+ * @since 3.0.0
18
+ * @package WooCommerce/Classes
19
+ * @category Class
20
+ * @author WooThemes
21
+ */
22
+ class WC_DateTime extends \DateTime {
23
+
24
+ /**
25
+ * Output an ISO 8601 date string in local timezone.
26
+ *
27
+ * @since 3.0.0
28
+ * @return string
29
+ */
30
+ public function __toString() {
31
+ return $this->format( DATE_ATOM );
32
+ }
33
+
34
+ /**
35
+ * Missing in PHP 5.2.
36
+ *
37
+ * @since 3.0.0
38
+ * @return int
39
+ */
40
+ public function getTimestamp() {
41
+ return method_exists( 'DateTime', 'getTimestamp' ) ? parent::getTimestamp() : $this->format( 'U' );
42
+ }
43
+
44
+ /**
45
+ * Get the timestamp with the WordPress timezone offset added or subtracted.
46
+ *
47
+ * @since 3.0.0
48
+ * @return int
49
+ */
50
+ public function getOffsetTimestamp() {
51
+ return $this->getTimestamp() + $this->getOffset();
52
+ }
53
+
54
+ /**
55
+ * Format a date based on the offset timestamp.
56
+ *
57
+ * @since 3.0.0
58
+ * @param string $format
59
+ * @return string
60
+ */
61
+ public function date( $format ) {
62
+ return gmdate( $format, $this->getOffsetTimestamp() );
63
+ }
64
+
65
+ /**
66
+ * Return a localised date based on offset timestamp. Wrapper for date_i18n function.
67
+ *
68
+ * @since 3.0.0
69
+ * @param string $format
70
+ * @return string
71
+ */
72
+ public function date_i18n( $format = 'Y-m-d' ) {
73
+ return date_i18n( $format, $this->getOffsetTimestamp() );
74
+ }
75
+ }
76
+
77
+ endif; // Class exists check
includes/compatibility/class-wc-order-compatibility.php ADDED
@@ -0,0 +1,387 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Derived from SkyVerge WooCommerce Plugin Framework https://github.com/skyverge/wc-plugin-framework/
4
+ */
5
+
6
+ namespace WPO\WC\PDF_Invoices\Compatibility;
7
+
8
+ defined( 'ABSPATH' ) or exit;
9
+
10
+ if ( ! class_exists( '\\WPO\\WC\\PDF_Invoices\\Compatibility\\Order' ) ) :
11
+
12
+ /**
13
+ * WooCommerce order compatibility class.
14
+ *
15
+ * @since 4.6.0-dev
16
+ */
17
+ class Order extends Data {
18
+
19
+
20
+ /** @var array mapped compatibility properties, as `$new_prop => $old_prop` */
21
+ protected static $compat_props = array(
22
+ 'date_completed' => 'completed_date',
23
+ 'date_paid' => 'paid_date',
24
+ 'date_modified' => 'modified_date',
25
+ 'date_created' => 'order_date',
26
+ 'customer_id' => 'customer_user',
27
+ 'discount' => 'cart_discount',
28
+ 'discount_tax' => 'cart_discount_tax',
29
+ 'shipping_total' => 'total_shipping',
30
+ 'type' => 'order_type',
31
+ 'currency' => 'order_currency',
32
+ 'version' => 'order_version',
33
+ );
34
+
35
+
36
+ /**
37
+ * Backports WC_Order::get_id() method to pre-2.6.0
38
+ *
39
+ * @since 4.2.0
40
+ * @param \WC_Order $order order object
41
+ * @return string|int order ID
42
+ */
43
+ public static function get_id( $order ) {
44
+
45
+ if ( method_exists( $order, 'get_id' ) ) {
46
+
47
+ return $order->get_id();
48
+
49
+ } else {
50
+
51
+ return isset($order->id) ? $order->id : false;
52
+ }
53
+ }
54
+
55
+
56
+ /**
57
+ * Gets an order property.
58
+ *
59
+ * @since 4.6.0-dev
60
+ * @param \WC_Order $object the order object
61
+ * @param string $prop the property name
62
+ * @param string $context if 'view' then the value will be filtered
63
+ * @return mixed
64
+ */
65
+ public static function get_prop( $object, $prop, $context = 'edit', $compat_props = array() ) {
66
+
67
+ // backport a few specific properties to pre-3.0
68
+ if ( WC_Core::is_wc_version_lt_3_0() ) {
69
+
70
+ // converge the shipping total prop for the raw context
71
+ if ( 'shipping_total' === $prop && 'view' !== $context ) {
72
+
73
+ $prop = 'order_shipping';
74
+
75
+ // get the post_parent and bail early
76
+ } elseif ( 'parent_id' === $prop ) {
77
+
78
+ return $object->post->post_parent;
79
+ }
80
+ }
81
+
82
+ $value = parent::get_prop( $object, $prop, $context, self::$compat_props );
83
+
84
+ // 3.0+ date getters return a DateTime object, where previously MySQL date strings were returned
85
+ if ( WC_Core::is_wc_version_lt_3_0() && in_array( $prop, array( 'date_completed', 'date_paid', 'date_modified', 'date_created' ), true ) && ! is_numeric( $value ) ) {
86
+ if ( is_numeric( $value ) ) {
87
+ $value = new WC_DateTime( "@{$value}", new \DateTimeZone( 'UTC' ) );
88
+ $value->setTimezone( new \DateTimeZone( wc_timezone_string() ) );
89
+ } else {
90
+ $value = new WC_DateTime( $value, new \DateTimeZone( wc_timezone_string() ) );
91
+ $value->setTimezone( new \DateTimeZone( wc_timezone_string() ) );
92
+ }
93
+ }
94
+
95
+ return $value;
96
+ }
97
+
98
+
99
+ /**
100
+ * Sets an order's properties.
101
+ *
102
+ * Note that this does not save any data to the database.
103
+ *
104
+ * @since 4.6.0-dev
105
+ * @param \WC_Order $object the order object
106
+ * @param array $props the new properties as $key => $value
107
+ * @return \WC_Order
108
+ */
109
+ public static function set_props( $object, $props, $compat_props = array() ) {
110
+
111
+ return parent::set_props( $object, $props, self::$compat_props );
112
+ }
113
+
114
+ /**
115
+ * Backports WC_Order::set_address_prop() to pre-3.0
116
+ * Saves by default.
117
+ *
118
+ * @since 4.6.0-dev
119
+ * @param \WC_Order $order the order object
120
+ * @param string $prop Name of prop to set.
121
+ * @param string $address Name of address to set. billing or shipping.
122
+ * @param mixed $value Value of the prop.
123
+ * @param bool $save whether to save the order/property
124
+ * @return \WC_Order
125
+ */
126
+ public static function set_address_prop( \WC_Order $order, $prop, $address = 'billing', $value, $save = true ) {
127
+ if ( WC_Core::is_wc_version_gte_3_0() ) {
128
+ if ( is_callable( array( $order, "set_{$address}_{$prop}" ) ) ) {
129
+ $order->{"set_{$address}_{$prop}"}( $value );
130
+ if ($save === true) {
131
+ $order->save();
132
+ }
133
+ }
134
+ } else {
135
+ // wc 2.6 or older
136
+ if ($save === true) {
137
+ // store directly in postmeta
138
+ update_post_meta( $order->id, "_{$address}_{$prop}", $value );
139
+ } else {
140
+ // only change property in the order
141
+ $order->$prop = $value;
142
+ }
143
+ }
144
+
145
+ return $order;
146
+ }
147
+
148
+ /**
149
+ * Implements WC_Order::get_item_meta for 3.0+
150
+ * @param \WC_Order $order the order object
151
+ * @param int $item_id the item id
152
+ * @param int $key the meta key
153
+ * @param boolean $single single or multiple
154
+ * @return mixed item meta
155
+ */
156
+ public static function get_item_meta( $object, $item_id, $key = '', $single = false ) {
157
+ if (function_exists('wc_get_order_item_meta')) {
158
+ $item_meta = wc_get_order_item_meta( $item_id, $key, $single );
159
+ } else {
160
+ $item_meta = $object->get_item_meta( $item_id, $key, $single );
161
+ }
162
+ return $item_meta;
163
+ }
164
+
165
+ /**
166
+ * Backports WC_Order::get_status() to pre-3.0.0
167
+ *
168
+ * @since 4.6.0-dev
169
+ * @param \WC_Order $order the order object
170
+ * @return string order status
171
+ */
172
+ public static function get_status( \WC_Order $order ) {
173
+
174
+ if ( method_exists( $order, 'get_status' ) ) {
175
+ return $order->get_status();
176
+ } else {
177
+ return $order->status;
178
+ }
179
+ }
180
+
181
+ /**
182
+ * Order item CRUD compatibility method to add a coupon to an order.
183
+ *
184
+ * @since 4.6.0-dev
185
+ * @param \WC_Order $order the order object
186
+ * @param array $code the coupon code
187
+ * @param int $discount the discount amount.
188
+ * @param int $discount_tax the discount tax amount.
189
+ * @return int the order item ID
190
+ */
191
+ public static function add_coupon( \WC_Order $order, $code = array(), $discount = 0, $discount_tax = 0 ) {
192
+
193
+ if ( WC_Core::is_wc_version_gte_3_0() ) {
194
+
195
+ $item = new \WC_Order_Item_Coupon();
196
+
197
+ $item->set_props( array(
198
+ 'code' => $code,
199
+ 'discount' => $discount,
200
+ 'discount_tax' => $discount_tax,
201
+ 'order_id' => $order->get_id(),
202
+ ) );
203
+
204
+ $item->save();
205
+
206
+ $order->add_item( $item );
207
+
208
+ return $item->get_id();
209
+
210
+ } else {
211
+
212
+ return $order->add_coupon( $code, $discount, $discount_tax );
213
+ }
214
+ }
215
+
216
+
217
+ /**
218
+ * Order item CRUD compatibility method to add a fee to an order.
219
+ *
220
+ * @since 4.6.0-dev
221
+ * @param \WC_Order $order the order object
222
+ * @param object $fee the fee to add
223
+ * @return int|\WC_Order_Item the order item ID
224
+ */
225
+ public static function add_fee( \WC_Order $order, $fee ) {
226
+
227
+ if ( WC_Core::is_wc_version_gte_3_0() ) {
228
+
229
+ $item = new \WC_Order_Item_Fee();
230
+
231
+ $item->set_props( array(
232
+ 'name' => $fee->name,
233
+ 'tax_class' => $fee->taxable ? $fee->tax_class : 0,
234
+ 'total' => $fee->amount,
235
+ 'total_tax' => $fee->tax,
236
+ 'taxes' => array(
237
+ 'total' => $fee->tax_data,
238
+ ),
239
+ 'order_id' => $order->get_id(),
240
+ ) );
241
+
242
+ $item->save();
243
+
244
+ $order->add_item( $item );
245
+
246
+ return $item->get_id();
247
+
248
+ } else {
249
+
250
+ return $order->add_fee( $fee );
251
+ }
252
+ }
253
+
254
+
255
+ /**
256
+ * Order item CRUD compatibility method to update an order coupon.
257
+ *
258
+ * @since 4.6.0-dev
259
+ * @param \WC_Order $order the order object
260
+ * @param int|\WC_Order_Item $item the order item ID
261
+ * @param array $args {
262
+ * The coupon item args.
263
+ *
264
+ * @type string $code the coupon code
265
+ * @type float $discount the coupon discount amount
266
+ * @type float $discount_tax the coupon discount tax amount
267
+ * }
268
+ * @return int|bool the order item ID or false on failure
269
+ */
270
+ public static function update_coupon( \WC_Order $order, $item, $args ) {
271
+
272
+ if ( WC_Core::is_wc_version_gte_3_0() ) {
273
+
274
+ if ( is_numeric( $item ) ) {
275
+ $item = $order->get_item( $item );
276
+ }
277
+
278
+ if ( ! is_object( $item ) || ! $item->is_type( 'coupon' ) ) {
279
+ return false;
280
+ }
281
+
282
+ if ( ! $order->get_id() ) {
283
+ $order->save();
284
+ }
285
+
286
+ $item->set_order_id( $order->get_id() );
287
+ $item->set_props( $args );
288
+ $item->save();
289
+
290
+ return $item->get_id();
291
+
292
+ } else {
293
+
294
+ // convert 3.0+ args for backwards compatibility
295
+ if ( isset( $args['discount'] ) ) {
296
+ $args['discount_amount'] = $args['discount'];
297
+ }
298
+ if ( isset( $args['discount_tax'] ) ) {
299
+ $args['discount_amount_tax'] = $args['discount_tax'];
300
+ }
301
+
302
+ return $order->update_coupon( $item, $args );
303
+ }
304
+ }
305
+
306
+
307
+ /**
308
+ * Order item CRUD compatibility method to update an order fee.
309
+ *
310
+ * @since 4.6.0-dev
311
+ * @param \WC_Order $order the order object
312
+ * @param int $item the order item ID
313
+ * @param array $args {
314
+ * The fee item args.
315
+ *
316
+ * @type string $name the fee name
317
+ * @type string $tax_class the fee's tax class
318
+ * @type float $line_total the fee total amount
319
+ * @type float $line_tax the fee tax amount
320
+ * }
321
+ * @return int|bool the order item ID or false on failure
322
+ */
323
+ public static function update_fee( \WC_Order $order, $item, $args ) {
324
+
325
+ if ( WC_Core::is_wc_version_gte_3_0() ) {
326
+
327
+ if ( is_numeric( $item ) ) {
328
+ $item = $order->get_item( $item );
329
+ }
330
+
331
+ if ( ! is_object( $item ) || ! $item->is_type( 'fee' ) ) {
332
+ return false;
333
+ }
334
+
335
+ if ( ! $order->get_id() ) {
336
+ $order->save();
337
+ }
338
+
339
+ $item->set_order_id( $order->get_id() );
340
+ $item->set_props( $args );
341
+ $item->save();
342
+
343
+ return $item->get_id();
344
+
345
+ } else {
346
+
347
+ return $order->update_fee( $item, $args );
348
+ }
349
+ }
350
+
351
+
352
+ /**
353
+ * Backports wc_reduce_stock_levels() to pre-3.0.0
354
+ *
355
+ * @since 4.6.0-dev
356
+ * @param \WC_Order $order the order object
357
+ */
358
+ public static function reduce_stock_levels( \WC_Order $order ) {
359
+
360
+ if ( WC_Core::is_wc_version_gte_3_0() ) {
361
+ wc_reduce_stock_levels( $order->get_id() );
362
+ } else {
363
+ $order->reduce_order_stock();
364
+ }
365
+ }
366
+
367
+
368
+ /**
369
+ * Backports wc_update_total_sales_counts() to pre-3.0.0
370
+ *
371
+ * @since 4.6.0-dev
372
+ * @param \WC_Order $order the order object
373
+ */
374
+ public static function update_total_sales_counts( \WC_Order $order ) {
375
+
376
+ if ( WC_Core::is_wc_version_gte_3_0() ) {
377
+ wc_update_total_sales_counts( $order->get_id() );
378
+ } else {
379
+ $order->record_product_sales();
380
+ }
381
+ }
382
+
383
+
384
+ }
385
+
386
+
387
+ endif; // Class exists check
includes/compatibility/class-wc-product-compatibility.php ADDED
@@ -0,0 +1,288 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Derived from SkyVerge WooCommerce Plugin Framework https://github.com/skyverge/wc-plugin-framework/
4
+ */
5
+
6
+ namespace WPO\WC\PDF_Invoices\Compatibility;
7
+
8
+ defined( 'ABSPATH' ) or exit;
9
+
10
+ if ( ! class_exists( '\\WPO\\WC\\PDF_Invoices\\Compatibility\\Product' ) ) :
11
+
12
+ /**
13
+ * WooCommerce product compatibility class.
14
+ *
15
+ * @since 4.6.0-dev
16
+ */
17
+ class Product extends Data {
18
+
19
+
20
+ /** @var array mapped compatibility properties, as `$new_prop => $old_prop` */
21
+ protected static $compat_props = array(
22
+ 'catalog_visibility' => 'visibility',
23
+ 'date_on_sale_from' => 'sale_price_dates_from',
24
+ 'date_on_sale_to' => 'sale_price_dates_to',
25
+ 'gallery_image_ids' => 'product_image_gallery',
26
+ 'cross_sell_ids' => 'crosssell_ids',
27
+ );
28
+
29
+
30
+ /**
31
+ * Backports WC_Product::get_id() method to 2.4.x
32
+ *
33
+ * @link https://github.com/woothemes/woocommerce/pull/9765
34
+ *
35
+ * @since 4.2.0
36
+ * @param \WC_Product $product product object
37
+ * @return string|int product ID
38
+ */
39
+ public static function get_id( \WC_Product $product ) {
40
+
41
+ if ( self::is_wc_version_gte_2_5() ) {
42
+
43
+ return $product->get_id();
44
+
45
+ } else {
46
+
47
+ return $product->is_type( 'variation' ) ? $product->variation_id : $product->id;
48
+ }
49
+ }
50
+
51
+
52
+ /**
53
+ * Gets a product property.
54
+ *
55
+ * @since 4.6.0-dev
56
+ * @param \WC_Product $object the product object
57
+ * @param string $prop the property name
58
+ * @param string $context if 'view' then the value will be filtered
59
+ * @return mixed
60
+ */
61
+ public static function get_prop( $object, $prop, $context = 'edit', $compat_props = array() ) {
62
+
63
+ // backport 'WC_Product::get_parent_id()' to pre-3.0
64
+ if ( WC_Core::is_wc_version_lt_3_0() && 'parent_id' === $prop ) {
65
+ $prop = 'id';
66
+ $context = $object->is_type( 'variation' ) ? 'raw' : $context;
67
+ }
68
+
69
+ return parent::get_prop( $object, $prop, $context, self::$compat_props );
70
+ }
71
+
72
+
73
+ /**
74
+ * Sets an products's properties.
75
+ *
76
+ * Note that this does not save any data to the database.
77
+ *
78
+ * @since 4.6.0-dev
79
+ * @param \WC_Product $object the product object
80
+ * @param array $props the new properties as $key => $value
81
+ * @return \WC_Product
82
+ */
83
+ public static function set_props( $object, $props, $compat_props = array() ) {
84
+
85
+ return parent::set_props( $object, $props, self::$compat_props );
86
+ }
87
+
88
+
89
+ /**
90
+ * Makes WC_Product::get_parent() available for WC 3.0+
91
+ *
92
+ * @since 4.6.0-dev
93
+ * @param \WC_Product $product the product object
94
+ * @return \WC_Product
95
+ */
96
+ public static function get_parent( \WC_Product $product ) {
97
+
98
+ if ( WC_Core::is_wc_version_gte_3_0() ) {
99
+ $parent = wc_get_product( $product->get_parent_id() );
100
+ } else {
101
+ $parent = $product->get_parent();
102
+ }
103
+
104
+ return $parent;
105
+ }
106
+
107
+
108
+
109
+ /**
110
+ * Makes WC_Product::get_dimensions() available for WC 3.0+
111
+ *
112
+ * @since 4.6.0-dev
113
+ * @param \WC_Product $product the product object
114
+ * @param string $rating Optional. The product rating
115
+ * @return string
116
+ */
117
+ public static function get_dimensions( \WC_Product $product ) {
118
+
119
+ if ( WC_Core::is_wc_version_gte_3_0() ) {
120
+ $dimensions = array(
121
+ 'length' => $product->get_length(),
122
+ 'width' => $product->get_width(),
123
+ 'height' => $product->get_height(),
124
+ );
125
+ return apply_filters( 'woocommerce_product_dimensions', wc_format_dimensions( $dimensions ), $product );
126
+ } else {
127
+ return $product->get_dimensions();
128
+ }
129
+ }
130
+
131
+
132
+ /**
133
+ * Backports wc_update_product_stock() to pre-3.0.0
134
+ *
135
+ * @since 4.6.0-dev
136
+ * @param \WC_Product $product the product object
137
+ * @param int $amount Optional. The new stock quantity
138
+ * @param string $mode Optional. Can be set, add, or subtract
139
+ * @return int
140
+ */
141
+ public static function wc_update_product_stock( \WC_Product $product, $amount = null, $mode = 'set' ) {
142
+
143
+ if ( WC_Core::is_wc_version_gte_3_0() ) {
144
+ return wc_update_product_stock( $product, $amount, $mode );
145
+ } else {
146
+ return $product->set_stock( $amount, $mode );
147
+ }
148
+ }
149
+
150
+
151
+ /**
152
+ * Backports wc_get_price_html_from_text() to pre-3.0.0
153
+ *
154
+ * @since 4.6.0-dev
155
+ * @param \WC_Product $product the product object
156
+ * @return string
157
+ */
158
+ public static function wc_get_price_html_from_text( \WC_Product $product ) {
159
+
160
+ if ( WC_Core::is_wc_version_gte_3_0() ) {
161
+ return wc_get_price_html_from_text();
162
+ } else {
163
+ return $product->get_price_html_from_text();
164
+ }
165
+ }
166
+
167
+
168
+ /**
169
+ * Backports wc_get_price_including_tax() to pre-3.0.0
170
+ *
171
+ * @since 4.6.0-dev
172
+ * @param \WC_Product $product the product object
173
+ * @param int $qty Optional. The quantity
174
+ * @param string $price Optional. The product price
175
+ * @return string
176
+ */
177
+ public static function wc_get_price_including_tax( \WC_Product $product, $qty = 1, $price = '' ) {
178
+
179
+ if ( WC_Core::is_wc_version_gte_3_0() ) {
180
+
181
+ return wc_get_price_including_tax( $product, array(
182
+ 'qty' => $qty,
183
+ 'price' => $price,
184
+ ) );
185
+
186
+ } else {
187
+
188
+ return $product->get_price_including_tax( $qty, $price );
189
+ }
190
+ }
191
+
192
+
193
+ /**
194
+ * Backports wc_get_price_excluding_tax() to pre-3.0.0
195
+ *
196
+ * @since 4.6.0-dev
197
+ * @param \WC_Product $product the product object
198
+ * @param int $qty Optional. The quantity
199
+ * @param string $price Optional. The product price
200
+ * @return string
201
+ */
202
+ public static function wc_get_price_excluding_tax( \WC_Product $product, $qty = 1, $price = '' ) {
203
+
204
+ if ( WC_Core::is_wc_version_gte_3_0() ) {
205
+
206
+ return wc_get_price_excluding_tax( $product, array(
207
+ 'qty' => $qty,
208
+ 'price' => $price,
209
+ ) );
210
+
211
+ } else {
212
+
213
+ return $product->get_price_excluding_tax( $qty, $price );
214
+ }
215
+ }
216
+
217
+
218
+ /**
219
+ * Backports wc_get_price_to_display() to pre-3.0.0
220
+ *
221
+ * @since 4.6.0-dev
222
+ * @param \WC_Product $product the product object
223
+ * @param string $price Optional. The product price
224
+ * @param int $qty Optional. The quantity
225
+ * @return string
226
+ */
227
+ public static function wc_get_price_to_display( \WC_Product $product, $price = '', $qty = 1 ) {
228
+
229
+ if ( WC_Core::is_wc_version_gte_3_0() ) {
230
+
231
+ return wc_get_price_to_display( $product, array(
232
+ 'qty' => $qty,
233
+ 'price' => $price,
234
+ ) );
235
+
236
+ } else {
237
+
238
+ return $product->get_display_price( $price, $qty );
239
+ }
240
+ }
241
+
242
+
243
+ /**
244
+ * Backports wc_get_product_category_list() to pre-3.0.0
245
+ *
246
+ * @since 4.6.0-dev
247
+ * @param \WC_Product $product the product object
248
+ * @param string $sep Optional. The list separator
249
+ * @param string $before Optional. To display before the list
250
+ * @param string $after Optional. To display after the list
251
+ * @return string
252
+ */
253
+ public static function wc_get_product_category_list( \WC_Product $product, $sep = ', ', $before = '', $after = '' ) {
254
+
255
+ if ( WC_Core::is_wc_version_gte_3_0() ) {
256
+
257
+ $id = $product->is_type( 'variation' ) ? $product->get_parent_id() : $product->get_id();
258
+
259
+ return wc_get_product_category_list( $id, $sep, $before, $after );
260
+
261
+ } else {
262
+
263
+ return $product->get_categories( $sep, $before, $after );
264
+ }
265
+ }
266
+
267
+
268
+ /**
269
+ * Backports wc_get_rating_html() to pre-3.0.0
270
+ *
271
+ * @since 4.6.0-dev
272
+ * @param \WC_Product $product the product object
273
+ * @param string $rating Optional. The product rating
274
+ * @return string
275
+ */
276
+ public static function wc_get_rating_html( \WC_Product $product, $rating = null ) {
277
+
278
+ if ( WC_Core::is_wc_version_gte_3_0() ) {
279
+ return wc_get_rating_html( $rating );
280
+ } else {
281
+ return $product->get_rating_html( $rating );
282
+ }
283
+ }
284
+
285
+ }
286
+
287
+
288
+ endif; // Class exists check
lib/dompdf/include/table_frame_decorator.cls.php CHANGED
@@ -176,9 +176,11 @@ class Table_Frame_Decorator extends Frame_Decorator {
176
  */
177
  static function find_parent_table(Frame $frame) {
178
 
179
- while ( $frame = $frame->get_parent() )
180
- if ( $frame->is_table() )
181
  break;
 
 
182
 
183
  return $frame;
184
  }
176
  */
177
  static function find_parent_table(Frame $frame) {
178
 
179
+ while ( $frame = $frame->get_parent() ) {
180
+ if ( $frame->is_table() ) {
181
  break;
182
+ }
183
+ }
184
 
185
  return $frame;
186
  }
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: pomegranate
3
  Tags: woocommerce, pdf, invoices, packing slips, print, delivery notes, invoice, packing slip, export, email, bulk, automatic
4
  Requires at least: 3.5
5
  Tested up to: 4.7
6
- Stable tag: 1.5.39
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -99,6 +99,13 @@ There's a setting on the Status tab of the settings page that allows you to togg
99
 
100
  == Changelog ==
101
 
 
 
 
 
 
 
 
102
  = 1.5.39 =
103
  * Feature: new template action hooks `wpo_wcpdf_before_document` & `wpo_wcpdf_after_document`
104
  * Tweak: In totals, emphasize order total rather than last item
@@ -509,5 +516,5 @@ There's a setting on the Status tab of the settings page that allows you to togg
509
 
510
  == Upgrade Notice ==
511
 
512
- = 1.5 =
513
- Version 1.5 changes where temporary files are stored - everything is now stored centrally in the WP uploads folder. For backwards compatibility, this feature is turned off by default, but we recommend to use the new folders. Check the plugin Status panel for more information!
3
  Tags: woocommerce, pdf, invoices, packing slips, print, delivery notes, invoice, packing slip, export, email, bulk, automatic
4
  Requires at least: 3.5
5
  Tested up to: 4.7
6
+ Stable tag: 1.6.0
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
99
 
100
  == Changelog ==
101
 
102
+ = 1.6.0 =
103
+ * WooCommerce 3.0 Compatible
104
+ * **Requires PHP version 5.3 or higher**
105
+ * Fix: Invoice number display in mobile view
106
+ * Fix: Update formatted invoice number in order meta when number is altered
107
+ * Tweak: Avoid PHP7 scan false positives in DomPDF
108
+
109
  = 1.5.39 =
110
  * Feature: new template action hooks `wpo_wcpdf_before_document` & `wpo_wcpdf_after_document`
111
  * Tweak: In totals, emphasize order total rather than last item
516
 
517
  == Upgrade Notice ==
518
 
519
+ = 1.6 =
520
+ Important: Version 1.6 requires PHP 5.3 or higher to run!
woocommerce-pdf-invoices-packingslips.php CHANGED
@@ -3,13 +3,14 @@
3
  * Plugin Name: WooCommerce PDF Invoices & Packing Slips
4
  * Plugin URI: http://www.wpovernight.com
5
  * Description: Create, print & email PDF invoices & packing slips for WooCommerce orders.
6
- * Version: 1.5.39
7
  * Author: Ewout Fernhout
8
  * Author URI: http://www.wpovernight.com
9
  * License: GPLv2 or later
10
  * License URI: http://www.opensource.org/licenses/gpl-license.php
11
  * Text Domain: wpo_wcpdf
12
  */
 
13
 
14
  if ( !class_exists( 'WooCommerce_PDF_Invoices' ) ) {
15
 
@@ -25,6 +26,20 @@ if ( !class_exists( 'WooCommerce_PDF_Invoices' ) ) {
25
  public $settings;
26
  public $export;
27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  /**
29
  * Constructor
30
  */
@@ -33,7 +48,7 @@ if ( !class_exists( 'WooCommerce_PDF_Invoices' ) ) {
33
  self::$plugin_basename = plugin_basename(__FILE__);
34
  self::$plugin_url = plugin_dir_url(self::$plugin_basename);
35
  self::$plugin_path = trailingslashit(dirname(__FILE__));
36
- self::$version = '1.5.39';
37
 
38
  // load the localisation & classes
39
  add_action( 'plugins_loaded', array( $this, 'translations' ) ); // or use init?
@@ -80,6 +95,14 @@ if ( !class_exists( 'WooCommerce_PDF_Invoices' ) ) {
80
  include_once( 'includes/class-wcpdf-settings.php' );
81
  include_once( 'includes/class-wcpdf-writepanels.php' );
82
  include_once( 'includes/class-wcpdf-export.php' );
 
 
 
 
 
 
 
 
83
  }
84
 
85
 
@@ -87,16 +110,22 @@ if ( !class_exists( 'WooCommerce_PDF_Invoices' ) ) {
87
  * Instantiate classes when woocommerce is activated
88
  */
89
  public function load_classes() {
90
- if ( $this->is_woocommerce_activated() ) {
91
- $this->includes();
92
- $this->settings = new WooCommerce_PDF_Invoices_Settings();
93
- $this->writepanels = new WooCommerce_PDF_Invoices_Writepanels();
94
- $this->export = new WooCommerce_PDF_Invoices_Export();
95
- } else {
96
- // display notice instead
97
  add_action( 'admin_notices', array ( $this, 'need_woocommerce' ) );
 
98
  }
99
 
 
 
 
 
 
 
 
 
 
 
 
100
  }
101
 
102
  /**
@@ -127,6 +156,18 @@ if ( !class_exists( 'WooCommerce_PDF_Invoices' ) ) {
127
  echo $message;
128
  }
129
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  /** Lifecycle methods *******************************************************
131
  * Because register_activation_hook only runs when the plugin is manually
132
  * activated by the user, we're checking the current version against the
@@ -221,453 +262,202 @@ if ( !class_exists( 'WooCommerce_PDF_Invoices' ) ) {
221
  * Get template name from slug
222
  */
223
  public function get_template_name ( $template_type ) {
224
- switch ( $template_type ) {
225
- case 'invoice':
226
- $template_name = apply_filters( 'wpo_wcpdf_invoice_title', __( 'Invoice', 'wpo_wcpdf' ) );
227
- break;
228
- case 'packing-slip':
229
- $template_name = apply_filters( 'wpo_wcpdf_packing_slip_title', __( 'Packing Slip', 'wpo_wcpdf' ) );
230
- break;
231
- default:
232
- // try to 'unslug' the name
233
- $template_name = ucwords( str_replace( array( '_', '-' ), ' ', $template_type ) );
234
- break;
235
- }
236
-
237
- return apply_filters( 'wpo_wcpdf_template_name', $template_name, $template_type );
238
  }
239
 
240
  /**
241
  * Output template styles
242
  */
243
  public function template_styles() {
244
- $css = apply_filters( 'wpo_wcpdf_template_styles_file', $this->export->template_path. '/' .'style.css' );
245
-
246
- ob_start();
247
- if (file_exists($css)) {
248
- include($css);
249
- }
250
- $html = ob_get_clean();
251
- $html = apply_filters( 'wpo_wcpdf_template_styles', $html );
252
-
253
- echo $html;
254
  }
255
 
256
  /**
257
  * Return logo id
258
  */
259
  public function get_header_logo_id() {
260
- if (isset($this->settings->template_settings['header_logo'])) {
261
- return apply_filters( 'wpo_wcpdf_header_logo_id', $this->settings->template_settings['header_logo'] );
262
- }
263
  }
264
 
265
  /**
266
  * Show logo html
267
  */
268
  public function header_logo() {
269
- if ($this->get_header_logo_id()) {
270
- $attachment_id = $this->get_header_logo_id();
271
- $company = isset($this->settings->template_settings['shop_name'])? $this->settings->template_settings['shop_name'] : '';
272
- if( $attachment_id ) {
273
- $attachment = wp_get_attachment_image_src( $attachment_id, 'full', false );
274
-
275
- $attachment_src = $attachment[0];
276
- $attachment_width = $attachment[1];
277
- $attachment_height = $attachment[2];
278
-
279
- $attachment_path = get_attached_file( $attachment_id );
280
-
281
- if ( apply_filters('wpo_wcpdf_use_path', true) && file_exists($attachment_path) ) {
282
- $src = $attachment_path;
283
- } else {
284
- $src = $attachment_src;
285
- }
286
-
287
- printf('<img src="%1$s" width="%2$d" height="%3$d" alt="%4$s" />', $src, $attachment_width, $attachment_height, esc_attr( $company ) );
288
- }
289
- }
290
  }
291
 
292
  /**
293
  * Return/Show custom company name or default to blog name
294
  */
295
  public function get_shop_name() {
296
- if (!empty($this->settings->template_settings['shop_name'])) {
297
- $name = trim( $this->settings->template_settings['shop_name'] );
298
- return apply_filters( 'wpo_wcpdf_shop_name', wptexturize( $name ) );
299
- } else {
300
- return apply_filters( 'wpo_wcpdf_shop_name', get_bloginfo( 'name' ) );
301
- }
302
  }
303
  public function shop_name() {
304
- echo $this->get_shop_name();
305
  }
306
 
307
  /**
308
  * Return/Show shop/company address if provided
309
  */
310
  public function get_shop_address() {
311
- $shop_address = apply_filters( 'wpo_wcpdf_shop_address', wpautop( wptexturize( $this->settings->template_settings['shop_address'] ) ) );
312
- if (!empty($shop_address)) {
313
- return $shop_address;
314
- } else {
315
- return false;
316
- }
317
  }
318
  public function shop_address() {
319
- echo $this->get_shop_address();
320
  }
321
 
322
  /**
323
  * Check if billing address and shipping address are equal
324
  */
325
  public function ships_to_different_address() {
326
- // always prefer parent address for refunds
327
- if ( get_post_type( $this->export->order->id ) == 'shop_order_refund' && $parent_order_id = wp_get_post_parent_id( $this->export->order->id ) ) {
328
- // temporarily switch order to make all filters / order calls work correctly
329
- $order_meta = get_post_meta( $parent_order_id );
330
- } else {
331
- $order_meta = get_post_meta( $this->export->order->id );
332
- }
333
-
334
- $address_comparison_fields = apply_filters( 'wpo_wcpdf_address_comparison_fields', array(
335
- 'first_name',
336
- 'last_name',
337
- 'company',
338
- 'address_1',
339
- 'address_2',
340
- 'city',
341
- 'state',
342
- 'postcode',
343
- 'country'
344
- ) );
345
-
346
- foreach ($address_comparison_fields as $address_field) {
347
- $billing_field = isset( $order_meta['_billing_'.$address_field] ) ? $order_meta['_billing_'.$address_field] : '';
348
- $shipping_field = isset( $order_meta['_shipping_'.$address_field] ) ? $order_meta['_shipping_'.$address_field] : '';
349
- if ( $shipping_field != $billing_field ) {
350
- // this address field is different -> ships to different address!
351
- return true;
352
- }
353
- }
354
-
355
- //if we got here, it means the addresses are equal -> doesn't ship to different address!
356
- return apply_filters( 'wpo_wcpdf_ships_to_different_address', false, $order_meta );
357
  }
358
 
359
  /**
360
  * Return/Show billing address
361
  */
362
  public function get_billing_address() {
363
- // always prefer parent billing address for refunds
364
- if ( get_post_type( $this->export->order->id ) == 'shop_order_refund' && $parent_order_id = wp_get_post_parent_id( $this->export->order->id ) ) {
365
- // temporarily switch order to make all filters / order calls work correctly
366
- $current_order = $this->export->order;
367
- $this->export->order = new WC_Order( $parent_order_id );
368
- $address = apply_filters( 'wpo_wcpdf_billing_address', $this->export->order->get_formatted_billing_address() );
369
- // switch back & unset
370
- $this->export->order = $current_order;
371
- unset($current_order);
372
- } elseif ( $address = $this->export->order->get_formatted_billing_address() ) {
373
- // regular shop_order
374
- $address = apply_filters( 'wpo_wcpdf_billing_address', $address );
375
- } else {
376
- // no address
377
- $address = apply_filters( 'wpo_wcpdf_billing_address', __('N/A', 'wpo_wcpdf') );
378
- }
379
-
380
- return $address;
381
  }
382
  public function billing_address() {
383
- echo $this->get_billing_address();
384
  }
385
 
386
  /**
387
  * Return/Show billing email
388
  */
389
  public function get_billing_email() {
390
- $billing_email = $this->export->order->billing_email;
391
-
392
- if ( !$billing_email && $parent_order_id = wp_get_post_parent_id( $this->export->order->id ) ) {
393
- // try parent
394
- $billing_email = get_post_meta( $parent_order_id, '_billing_email', true );
395
- }
396
-
397
- return apply_filters( 'wpo_wcpdf_billing_email', $billing_email );
398
  }
399
  public function billing_email() {
400
- echo $this->get_billing_email();
401
  }
402
 
403
  /**
404
  * Return/Show billing phone
405
  */
406
  public function get_billing_phone() {
407
- $billing_phone = $this->export->order->billing_phone;
408
-
409
- if ( !$billing_phone && $parent_order_id = wp_get_post_parent_id( $this->export->order->id ) ) {
410
- // try parent
411
- $billing_phone = get_post_meta( $parent_order_id, '_billing_phone', true );
412
- }
413
-
414
- return apply_filters( 'wpo_wcpdf_billing_phone', $billing_phone );
415
  }
416
  public function billing_phone() {
417
- echo $this->get_billing_phone();
418
  }
419
 
420
  /**
421
  * Return/Show shipping address
422
  */
423
  public function get_shipping_address() {
424
- // always prefer parent shipping address for refunds
425
- if ( get_post_type( $this->export->order->id ) == 'shop_order_refund' && $parent_order_id = wp_get_post_parent_id( $this->export->order->id ) ) {
426
- // temporarily switch order to make all filters / order calls work correctly
427
- $current_order = $this->export->order;
428
- $this->export->order = new WC_Order( $parent_order_id );
429
- $address = apply_filters( 'wpo_wcpdf_shipping_address', $this->export->order->get_formatted_shipping_address() );
430
- // switch back & unset
431
- $this->export->order = $current_order;
432
- unset($current_order);
433
- } elseif ( $address = $this->export->order->get_formatted_shipping_address() ) {
434
- // regular shop_order
435
- $address = apply_filters( 'wpo_wcpdf_shipping_address', $address );
436
- } else {
437
- // no address
438
- $address = apply_filters( 'wpo_wcpdf_shipping_address', __('N/A', 'wpo_wcpdf') );
439
- }
440
-
441
- return $address;
442
  }
443
  public function shipping_address() {
444
- echo $this->get_shipping_address();
445
  }
446
 
447
  /**
448
  * Return/Show a custom field
449
  */
450
  public function get_custom_field( $field_name ) {
451
- $custom_field = get_post_meta($this->export->order->id,$field_name,true);
452
-
453
- if ( !$custom_field && $parent_order_id = wp_get_post_parent_id( $this->export->order->id ) ) {
454
- // try parent
455
- $custom_field = get_post_meta( $parent_order_id, $field_name, true );
456
- }
457
-
458
- return apply_filters( 'wpo_wcpdf_billing_custom_field', $custom_field );
459
  }
460
  public function custom_field( $field_name, $field_label = '', $display_empty = false ) {
461
- $custom_field = $this->get_custom_field( $field_name );
462
- if (!empty($field_label)){
463
- // add a a trailing space to the label
464
- $field_label .= ' ';
465
- }
466
-
467
- if (!empty($custom_field) || $display_empty) {
468
- echo $field_label . nl2br ($custom_field);
469
- }
470
  }
471
 
472
  /**
473
  * Return/Show order notes
474
  */
475
  public function get_order_notes( $filter = 'customer' ) {
476
- if ( get_post_type( $this->export->order->id ) == 'shop_order_refund' && $parent_order_id = wp_get_post_parent_id( $this->export->order->id ) ) {
477
- $post_id = $parent_order_id;
478
- } else {
479
- $post_id = $this->export->order->id;
480
- }
481
-
482
- $args = array(
483
- 'post_id' => $post_id,
484
- 'approve' => 'approve',
485
- 'type' => 'order_note'
486
- );
487
-
488
- remove_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ), 10, 1 );
489
-
490
- $notes = get_comments( $args );
491
-
492
- add_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ), 10, 1 );
493
-
494
- if ( $notes ) {
495
- foreach( $notes as $key => $note ) {
496
- if ( $filter == 'customer' && !get_comment_meta( $note->comment_ID, 'is_customer_note', true ) ) {
497
- unset($notes[$key]);
498
- }
499
- if ( $filter == 'private' && get_comment_meta( $note->comment_ID, 'is_customer_note', true ) ) {
500
- unset($notes[$key]);
501
- }
502
- }
503
- return $notes;
504
- }
505
  }
506
  public function order_notes( $filter = 'customer' ) {
507
- $notes = $this->get_order_notes( $filter );
508
- if ( $notes ) {
509
- foreach( $notes as $note ) {
510
- ?>
511
- <div class="note_content">
512
- <?php echo wpautop( wptexturize( wp_kses_post( $note->comment_content ) ) ); ?>
513
- </div>
514
- <?php
515
- }
516
- }
517
  }
518
 
519
  /**
520
  * Return/Show the current date
521
  */
522
  public function get_current_date() {
523
- return apply_filters( 'wpo_wcpdf_date', date_i18n( get_option( 'date_format' ) ) );
524
  }
525
  public function current_date() {
526
- echo $this->get_current_date();
527
  }
528
 
529
  /**
530
  * Return/Show payment method
531
  */
532
  public function get_payment_method() {
533
- $payment_method_label = __( 'Payment method', 'wpo_wcpdf' );
534
-
535
- $payment_method = __( $this->export->order->payment_method_title, 'woocommerce' );
536
- if ( !$payment_method && $parent_order_id = wp_get_post_parent_id( $this->export->order->id ) ) {
537
- // try parent
538
- $payment_method = get_post_meta( $parent_order_id, '_payment_method_title', true );
539
- $payment_method = __( $payment_method, 'woocommerce' );
540
- }
541
-
542
- return apply_filters( 'wpo_wcpdf_payment_method', $payment_method );
543
  }
544
  public function payment_method() {
545
- echo $this->get_payment_method();
546
  }
547
 
548
  /**
549
  * Return/Show shipping method
550
  */
551
  public function get_shipping_method() {
552
- $shipping_method_label = __( 'Shipping method', 'wpo_wcpdf' );
553
- return apply_filters( 'wpo_wcpdf_shipping_method', __( $this->export->order->get_shipping_method(), 'woocommerce' ) );
554
  }
555
  public function shipping_method() {
556
- echo $this->get_shipping_method();
557
  }
558
 
559
  /**
560
  * Return/Show order number
561
  */
562
  public function get_order_number() {
563
- // try parent first
564
- if ( get_post_type( $this->export->order->id ) == 'shop_order_refund' && $parent_order_id = wp_get_post_parent_id( $this->export->order->id ) ) {
565
- $parent_order = new WC_Order( $parent_order_id );
566
- $order_number = $parent_order->get_order_number();
567
- } else {
568
- $order_number = $this->export->order->get_order_number();
569
- }
570
-
571
- // Trim the hash to have a clean number but still
572
- // support any filters that were applied before.
573
- $order_number = ltrim($order_number, '#');
574
- return apply_filters( 'wpo_wcpdf_order_number', $order_number);
575
  }
576
  public function order_number() {
577
- echo $this->get_order_number();
578
  }
579
 
580
  /**
581
  * Return/Show invoice number
582
  */
583
  public function get_invoice_number() {
584
- // try parent first
585
- if ( get_post_type( $this->export->order->id ) == 'shop_order_refund' && $parent_order_id = wp_get_post_parent_id( $this->export->order->id ) ) {
586
- $invoice_number = $this->export->get_invoice_number( $parent_order_id );
587
- } else {
588
- $invoice_number = $this->export->get_invoice_number( $this->export->order->id );
589
- }
590
-
591
- return $invoice_number;
592
  }
593
  public function invoice_number() {
594
- echo $this->get_invoice_number();
595
  }
596
 
597
  /**
598
  * Return/Show the order date
599
  */
600
  public function get_order_date() {
601
- if ( get_post_type( $this->export->order->id ) == 'shop_order_refund' && $parent_order_id = wp_get_post_parent_id( $this->export->order->id ) ) {
602
- $parent_order = new WC_Order( $parent_order_id );
603
- $order_date = $parent_order->order_date;
604
- } else {
605
- $order_date = $this->export->order->order_date;
606
- }
607
-
608
- $date = date_i18n( get_option( 'date_format' ), strtotime( $order_date ) );
609
- return apply_filters( 'wpo_wcpdf_order_date', $date, $order_date );
610
  }
611
  public function order_date() {
612
- echo $this->get_order_date();
613
  }
614
 
615
  /**
616
  * Return/Show the invoice date
617
  */
618
  public function get_invoice_date() {
619
- $invoice_date = get_post_meta($this->export->order->id,'_wcpdf_invoice_date',true);
620
-
621
- // add invoice date if it doesn't exist
622
- if ( empty($invoice_date) || !isset($invoice_date) ) {
623
- $invoice_date = current_time('mysql');
624
- update_post_meta( $this->export->order->id, '_wcpdf_invoice_date', $invoice_date );
625
- }
626
-
627
- $formatted_invoice_date = date_i18n( get_option( 'date_format' ), strtotime( $invoice_date ) );
628
-
629
- return apply_filters( 'wpo_wcpdf_invoice_date', $formatted_invoice_date, $invoice_date );
630
  }
631
  public function invoice_date() {
632
- echo $this->get_invoice_date();
633
  }
634
 
635
  /**
636
  * Return the order items
637
  */
638
  public function get_order_items() {
639
- return apply_filters( 'wpo_wcpdf_order_items', $this->export->get_order_items() );
640
  }
641
 
642
  /**
643
  * Return/show product attribute
644
  */
645
  public function get_product_attribute( $attribute_name, $product ) {
646
- // first, check the text attributes
647
- $attributes = $product->get_attributes();
648
- $attribute_key = @wc_attribute_taxonomy_name( $attribute_name );
649
- if (array_key_exists( sanitize_title( $attribute_name ), $attributes) ) {
650
- $attribute = $product->get_attribute ( $attribute_name );
651
- return $attribute;
652
- } elseif (array_key_exists( sanitize_title( $attribute_key ), $attributes) ) {
653
- $attribute = $product->get_attribute ( $attribute_key );
654
- return $attribute;
655
- }
656
-
657
- // not a text attribute, try attribute taxonomy
658
- $attribute_key = @wc_attribute_taxonomy_name( $attribute_name );
659
- $product_terms = @wc_get_product_terms( $product->id, $attribute_key, array( 'fields' => 'names' ) );
660
- // check if not empty, then display
661
- if ( !empty($product_terms) ) {
662
- $attribute = array_shift( $product_terms );
663
- return $attribute;
664
- } else {
665
- // no attribute under this name
666
- return false;
667
- }
668
  }
669
  public function product_attribute( $attribute_name, $product ) {
670
- echo $this->get_product_attribute( $attribute_name, $product );
671
  }
672
 
673
 
@@ -675,252 +465,61 @@ if ( !class_exists( 'WooCommerce_PDF_Invoices' ) ) {
675
  * Return the order totals listing
676
  */
677
  public function get_woocommerce_totals() {
678
- // get totals and remove the semicolon
679
- $totals = apply_filters( 'wpo_wcpdf_raw_order_totals', $this->export->order->get_order_item_totals(), $this->export->order );
680
-
681
- // remove the colon for every label
682
- foreach ( $totals as $key => $total ) {
683
- $label = $total['label'];
684
- $colon = strrpos( $label, ':' );
685
- if( $colon !== false ) {
686
- $label = substr_replace( $label, '', $colon, 1 );
687
- }
688
- $totals[$key]['label'] = $label;
689
- }
690
-
691
- // WC2.4 fix order_total for refunded orders
692
- if ( version_compare( WOOCOMMERCE_VERSION, '2.4', '>=' ) && isset($totals['order_total']) ) {
693
- $tax_display = $this->export->order->tax_display_cart;
694
- $totals['order_total']['value'] = wc_price( $this->export->order->get_total(), array( 'currency' => $this->export->order->get_order_currency() ) );
695
- $order_total = $this->export->order->get_total();
696
- $tax_string = '';
697
-
698
- // Tax for inclusive prices
699
- if ( wc_tax_enabled() && 'incl' == $tax_display ) {
700
- $tax_string_array = array();
701
-
702
- if ( 'itemized' == get_option( 'woocommerce_tax_total_display' ) ) {
703
- foreach ( $this->export->order->get_tax_totals() as $code => $tax ) {
704
- $tax_amount = $tax->formatted_amount;
705
- $tax_string_array[] = sprintf( '%s %s', $tax_amount, $tax->label );
706
- }
707
- } else {
708
- $tax_string_array[] = sprintf( '%s %s', wc_price( $this->export->order->get_total_tax() - $this->export->order->get_total_tax_refunded(), array( 'currency' => $this->export->order->get_order_currency() ) ), WC()->countries->tax_or_vat() );
709
- }
710
- if ( ! empty( $tax_string_array ) ) {
711
- if ( version_compare( WOOCOMMERCE_VERSION, '2.6', '>=' ) ) {
712
- $tax_string = ' ' . sprintf( __( '(includes %s)', 'woocommerce' ), implode( ', ', $tax_string_array ) );
713
- } else {
714
- // use old capitalized string
715
- $tax_string = ' ' . sprintf( __( '(Includes %s)', 'woocommerce' ), implode( ', ', $tax_string_array ) );
716
- }
717
- }
718
- }
719
-
720
- $totals['order_total']['value'] .= $tax_string;
721
- }
722
-
723
- // remove refund lines (shouldn't be in invoice)
724
- foreach ( $totals as $key => $total ) {
725
- if ( strpos($key, 'refund_') !== false ) {
726
- unset( $totals[$key] );
727
- }
728
- }
729
-
730
- return apply_filters( 'wpo_wcpdf_woocommerce_totals', $totals, $this->export->order );
731
  }
732
 
733
  /**
734
  * Return/show the order subtotal
735
  */
736
  public function get_order_subtotal( $tax = 'excl', $discount = 'incl' ) { // set $tax to 'incl' to include tax, same for $discount
737
- //$compound = ($discount == 'incl')?true:false;
738
-
739
- $subtotal = $this->export->order->get_subtotal_to_display( false, $tax );
740
-
741
- $subtotal = ($pos = strpos($subtotal, ' <small')) ? substr($subtotal, 0, $pos) : $subtotal; //removing the 'excluding tax' text
742
-
743
- $subtotal = array (
744
- 'label' => __('Subtotal', 'wpo_wcpdf'),
745
- 'value' => $subtotal,
746
- );
747
-
748
- return apply_filters( 'wpo_wcpdf_order_subtotal', $subtotal, $tax, $discount );
749
  }
750
  public function order_subtotal( $tax = 'excl', $discount = 'incl' ) {
751
- $subtotal = $this->get_order_subtotal( $tax, $discount );
752
- echo $subtotal['value'];
753
  }
754
 
755
  /**
756
  * Return/show the order shipping costs
757
  */
758
  public function get_order_shipping( $tax = 'excl' ) { // set $tax to 'incl' to include tax
759
- if ($tax == 'excl' ) {
760
- $shipping_costs = $this->export->wc_price( $this->export->order->order_shipping );
761
- } else {
762
- $shipping_costs = $this->export->wc_price( $this->export->order->order_shipping + $this->export->order->order_shipping_tax );
763
- }
764
-
765
- $shipping = array (
766
- 'label' => __('Shipping', 'wpo_wcpdf'),
767
- 'value' => $shipping_costs,
768
- 'tax' => $this->export->wc_price( $this->export->order->order_shipping_tax ),
769
- );
770
- return apply_filters( 'wpo_wcpdf_order_shipping', $shipping, $tax );
771
  }
772
  public function order_shipping( $tax = 'excl' ) {
773
- $shipping = $this->get_order_shipping( $tax );
774
- echo $shipping['value'];
775
  }
776
 
777
  /**
778
  * Return/show the total discount
779
  */
780
  public function get_order_discount( $type = 'total', $tax = 'incl' ) {
781
- if ( $tax == 'incl' ) {
782
- switch ($type) {
783
- case 'cart':
784
- // Cart Discount - pre-tax discounts. (deprecated in WC2.3)
785
- $discount_value = $this->export->order->get_cart_discount();
786
- break;
787
- case 'order':
788
- // Order Discount - post-tax discounts. (deprecated in WC2.3)
789
- $discount_value = $this->export->order->get_order_discount();
790
- break;
791
- case 'total':
792
- // Total Discount
793
- if ( version_compare( WOOCOMMERCE_VERSION, '2.3' ) >= 0 ) {
794
- $discount_value = $this->export->order->get_total_discount( false ); // $ex_tax = false
795
- } else {
796
- // WC2.2 and older: recalculate to include tax
797
- $discount_value = 0;
798
- $items = $this->export->order->get_items();;
799
- if( sizeof( $items ) > 0 ) {
800
- foreach( $items as $item ) {
801
- $discount_value += ($item['line_subtotal'] + $item['line_subtotal_tax']) - ($item['line_total'] + $item['line_tax']);
802
- }
803
- }
804
- }
805
-
806
- break;
807
- default:
808
- // Total Discount - Cart & Order Discounts combined
809
- $discount_value = $this->export->order->get_total_discount();
810
- break;
811
- }
812
- } else { // calculate discount excluding tax
813
- if ( version_compare( WOOCOMMERCE_VERSION, '2.3' ) >= 0 ) {
814
- $discount_value = $this->export->order->get_total_discount( true ); // $ex_tax = true
815
- } else {
816
- // WC2.2 and older: recalculate to exclude tax
817
- $discount_value = 0;
818
-
819
- $items = $this->export->order->get_items();;
820
- if( sizeof( $items ) > 0 ) {
821
- foreach( $items as $item ) {
822
- $discount_value += ($item['line_subtotal'] - $item['line_total']);
823
- }
824
- }
825
- }
826
- }
827
-
828
- $discount = array (
829
- 'label' => __('Discount', 'wpo_wcpdf'),
830
- 'value' => $this->export->wc_price($discount_value),
831
- 'raw_value' => $discount_value,
832
- );
833
-
834
- if ( round( $discount_value, 3 ) != 0 ) {
835
- return apply_filters( 'wpo_wcpdf_order_discount', $discount, $type, $tax );
836
- }
837
  }
838
  public function order_discount( $type = 'total', $tax = 'incl' ) {
839
- $discount = $this->get_order_discount( $type, $tax );
840
- echo $discount['value'];
841
  }
842
 
843
  /**
844
  * Return the order fees
845
  */
846
  public function get_order_fees( $tax = 'excl' ) {
847
- if ( $wcfees = $this->export->order->get_fees() ) {
848
- foreach( $wcfees as $id => $fee ) {
849
- if ($tax == 'excl' ) {
850
- $fee_price = $this->export->wc_price( $fee['line_total'] );
851
- } else {
852
- $fee_price = $this->export->wc_price( $fee['line_total'] + $fee['line_tax'] );
853
- }
854
-
855
- $fees[ $id ] = array(
856
- 'label' => $fee['name'],
857
- 'value' => $fee_price,
858
- 'line_total' => $this->export->wc_price($fee['line_total']),
859
- 'line_tax' => $this->export->wc_price($fee['line_tax'])
860
- );
861
- }
862
- return $fees;
863
- }
864
  }
865
 
866
  /**
867
  * Return the order taxes
868
  */
869
  public function get_order_taxes() {
870
- $tax_label = __( 'VAT', 'wpo_wcpdf' ); // register alternate label translation
871
- $tax_label = __( 'Tax rate', 'wpo_wcpdf' );
872
- $tax_rate_ids = $this->export->get_tax_rate_ids();
873
- if ($this->export->order->get_taxes()) {
874
- foreach ( $this->export->order->get_taxes() as $key => $tax ) {
875
- $taxes[ $key ] = array(
876
- 'label' => isset( $tax[ 'label' ] ) ? $tax[ 'label' ] : $tax[ 'name' ],
877
- 'value' => $this->export->wc_price( ( $tax[ 'tax_amount' ] + $tax[ 'shipping_tax_amount' ] ) ),
878
- 'rate_id' => $tax['rate_id'],
879
- 'tax_amount' => $tax['tax_amount'],
880
- 'shipping_tax_amount' => $tax['shipping_tax_amount'],
881
- 'rate' => isset( $tax_rate_ids[ $tax['rate_id'] ] ) ? ( (float) $tax_rate_ids[$tax['rate_id']]['tax_rate'] ) . ' %': '',
882
- );
883
- }
884
-
885
- return apply_filters( 'wpo_wcpdf_order_taxes', $taxes );
886
- }
887
  }
888
 
889
  /**
890
  * Return/show the order grand total
891
  */
892
  public function get_order_grand_total( $tax = 'incl' ) {
893
- if ( version_compare( WOOCOMMERCE_VERSION, '2.1' ) >= 0 ) {
894
- // WC 2.1 or newer is used
895
- $total_unformatted = $this->export->order->get_total();
896
- } else {
897
- // Backwards compatibility
898
- $total_unformatted = $this->export->order->get_order_total();
899
- }
900
-
901
- if ($tax == 'excl' ) {
902
- $total_tax = 0;
903
- foreach ( $this->export->order->get_taxes() as $tax ) {
904
- $total_tax += ( $tax[ 'tax_amount' ] + $tax[ 'shipping_tax_amount' ] );
905
- }
906
-
907
- $total = $this->export->wc_price( ( $total_unformatted - $total_tax ) );
908
- $label = __( 'Total ex. VAT', 'wpo_wcpdf' );
909
- } else {
910
- $total = $this->export->wc_price( ( $total_unformatted ) );
911
- $label = __( 'Total', 'wpo_wcpdf' );
912
- }
913
-
914
- $grand_total = array(
915
- 'label' => $label,
916
- 'value' => $total,
917
- );
918
-
919
- return apply_filters( 'wpo_wcpdf_order_grand_total', $grand_total, $tax );
920
  }
921
  public function order_grand_total( $tax = 'incl' ) {
922
- $grand_total = $this->get_order_grand_total( $tax );
923
- echo $grand_total['value'];
924
  }
925
 
926
 
@@ -928,11 +527,10 @@ if ( !class_exists( 'WooCommerce_PDF_Invoices' ) ) {
928
  * Return/Show shipping notes
929
  */
930
  public function get_shipping_notes() {
931
- $shipping_notes = wpautop( wptexturize( $this->export->order->customer_note ) );
932
- return apply_filters( 'wpo_wcpdf_shipping_notes', $shipping_notes );
933
  }
934
  public function shipping_notes() {
935
- echo $this->get_shipping_notes();
936
  }
937
 
938
 
@@ -940,55 +538,53 @@ if ( !class_exists( 'WooCommerce_PDF_Invoices' ) ) {
940
  * Return/Show shop/company footer imprint, copyright etc.
941
  */
942
  public function get_footer() {
943
- if (isset($this->settings->template_settings['footer'])) {
944
- $footer = wpautop( wptexturize( $this->settings->template_settings[ 'footer' ] ) );
945
- return apply_filters( 'wpo_wcpdf_footer', $footer );
946
- }
947
  }
948
  public function footer() {
949
- echo $this->get_footer();
950
  }
951
 
952
  /**
953
  * Return/Show Extra field 1
954
  */
955
  public function get_extra_1() {
956
- if (isset($this->settings->template_settings['extra_1'])) {
957
- $extra_1 = nl2br( wptexturize( $this->settings->template_settings[ 'extra_1' ] ) );
958
- return apply_filters( 'wpo_wcpdf_extra_1', $extra_1 );
959
- }
960
  }
961
  public function extra_1() {
962
- echo $this->get_extra_1();
963
  }
964
 
965
  /**
966
  * Return/Show Extra field 2
967
  */
968
  public function get_extra_2() {
969
- if (isset($this->settings->template_settings['extra_2'])) {
970
- $extra_2 = nl2br( wptexturize( $this->settings->template_settings[ 'extra_2' ] ) );
971
- return apply_filters( 'wpo_wcpdf_extra_2', $extra_2 );
972
- }
973
  }
974
  public function extra_2() {
975
- echo $this->get_extra_2();
976
  }
977
 
978
- /**
979
  * Return/Show Extra field 3
980
  */
981
  public function get_extra_3() {
982
- if (isset($this->settings->template_settings['extra_3'])) {
983
- $extra_3 = nl2br( wptexturize( $this->settings->template_settings[ 'extra_3' ] ) );
984
- return apply_filters( 'wpo_wcpdf_extra_3', $extra_3 );
985
- }
986
  }
987
  public function extra_3() {
988
- echo $this->get_extra_3();
989
- }
990
  }
991
  }
992
 
993
- // Load main plugin class
994
- $wpo_wcpdf = new WooCommerce_PDF_Invoices();
 
 
 
 
 
 
 
 
 
 
3
  * Plugin Name: WooCommerce PDF Invoices & Packing Slips
4
  * Plugin URI: http://www.wpovernight.com
5
  * Description: Create, print & email PDF invoices & packing slips for WooCommerce orders.
6
+ * Version: 1.6.0
7
  * Author: Ewout Fernhout
8
  * Author URI: http://www.wpovernight.com
9
  * License: GPLv2 or later
10
  * License URI: http://www.opensource.org/licenses/gpl-license.php
11
  * Text Domain: wpo_wcpdf
12
  */
13
+ defined( 'ABSPATH' ) or exit;
14
 
15
  if ( !class_exists( 'WooCommerce_PDF_Invoices' ) ) {
16
 
26
  public $settings;
27
  public $export;
28
 
29
+ protected static $_instance = null;
30
+
31
+ /**
32
+ * Main Plugin Instance
33
+ *
34
+ * Ensures only one instance of plugin is loaded or can be loaded.
35
+ */
36
+ public static function instance() {
37
+ if ( is_null( self::$_instance ) ) {
38
+ self::$_instance = new self();
39
+ }
40
+ return self::$_instance;
41
+ }
42
+
43
  /**
44
  * Constructor
45
  */
48
  self::$plugin_basename = plugin_basename(__FILE__);
49
  self::$plugin_url = plugin_dir_url(self::$plugin_basename);
50
  self::$plugin_path = trailingslashit(dirname(__FILE__));
51
+ self::$version = '1.6.0';
52
 
53
  // load the localisation & classes
54
  add_action( 'plugins_loaded', array( $this, 'translations' ) ); // or use init?
95
  include_once( 'includes/class-wcpdf-settings.php' );
96
  include_once( 'includes/class-wcpdf-writepanels.php' );
97
  include_once( 'includes/class-wcpdf-export.php' );
98
+ include_once( 'includes/class-wcpdf-functions.php' );
99
+
100
+ // compatibility classes
101
+ include_once( 'includes/compatibility/abstract-wc-data-compatibility.php' );
102
+ include_once( 'includes/compatibility/class-wc-date-compatibility.php' );
103
+ include_once( 'includes/compatibility/class-wc-core-compatibility.php' );
104
+ include_once( 'includes/compatibility/class-wc-order-compatibility.php' );
105
+ include_once( 'includes/compatibility/class-wc-product-compatibility.php' );
106
  }
107
 
108
 
110
  * Instantiate classes when woocommerce is activated
111
  */
112
  public function load_classes() {
113
+ if ( $this->is_woocommerce_activated() === false ) {
 
 
 
 
 
 
114
  add_action( 'admin_notices', array ( $this, 'need_woocommerce' ) );
115
+ return;
116
  }
117
 
118
+ if ( version_compare( PHP_VERSION, '5.3', '<' ) ) {
119
+ add_action( 'admin_notices', array ( $this, 'required_php_version' ) );
120
+ return;
121
+ }
122
+
123
+ // all systems ready - GO!
124
+ $this->includes();
125
+ $this->settings = new WooCommerce_PDF_Invoices_Settings();
126
+ $this->writepanels = new WooCommerce_PDF_Invoices_Writepanels();
127
+ $this->export = new WooCommerce_PDF_Invoices_Export();
128
+ $this->functions = new WooCommerce_PDF_Invoices_Functions();
129
  }
130
 
131
  /**
156
  echo $message;
157
  }
158
 
159
+ /**
160
+ * PHP version requirement notice
161
+ */
162
+
163
+ public function required_php_version() {
164
+ $error = __( 'WooCommerce PDF Invoices & Packing Slips requires PHP 5.3 or higher (5.6 or higher recommended).', 'wpo_wcpdf' );
165
+ $how_to_update = __( 'How to update your PHP version', 'wpo_wcpdf' );
166
+ $message = sprintf('<div class="error"><p>%s</p><p><a href="%s">%s</a></p></div>', $error, 'http://docs.wpovernight.com/general/how-to-update-your-php-version/', $how_to_update);
167
+
168
+ echo $message;
169
+ }
170
+
171
  /** Lifecycle methods *******************************************************
172
  * Because register_activation_hook only runs when the plugin is manually
173
  * activated by the user, we're checking the current version against the
262
  * Get template name from slug
263
  */
264
  public function get_template_name ( $template_type ) {
265
+ return $this->functions->get_template_name( $template_type );
 
 
 
 
 
 
 
 
 
 
 
 
 
266
  }
267
 
268
  /**
269
  * Output template styles
270
  */
271
  public function template_styles() {
272
+ $this->functions->template_styles();
 
 
 
 
 
 
 
 
 
273
  }
274
 
275
  /**
276
  * Return logo id
277
  */
278
  public function get_header_logo_id() {
279
+ return $this->functions->get_header_logo_id();
 
 
280
  }
281
 
282
  /**
283
  * Show logo html
284
  */
285
  public function header_logo() {
286
+ $this->functions->header_logo();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
287
  }
288
 
289
  /**
290
  * Return/Show custom company name or default to blog name
291
  */
292
  public function get_shop_name() {
293
+ return $this->functions->get_shop_name();
 
 
 
 
 
294
  }
295
  public function shop_name() {
296
+ $this->functions->shop_name();
297
  }
298
 
299
  /**
300
  * Return/Show shop/company address if provided
301
  */
302
  public function get_shop_address() {
303
+ return $this->functions->get_shop_address();
 
 
 
 
 
304
  }
305
  public function shop_address() {
306
+ $this->functions->shop_address();
307
  }
308
 
309
  /**
310
  * Check if billing address and shipping address are equal
311
  */
312
  public function ships_to_different_address() {
313
+ return $this->functions->ships_to_different_address();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
314
  }
315
 
316
  /**
317
  * Return/Show billing address
318
  */
319
  public function get_billing_address() {
320
+ return $this->functions->get_billing_address();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
  }
322
  public function billing_address() {
323
+ $this->functions->billing_address();
324
  }
325
 
326
  /**
327
  * Return/Show billing email
328
  */
329
  public function get_billing_email() {
330
+ return $this->functions->get_billing_email();
 
 
 
 
 
 
 
331
  }
332
  public function billing_email() {
333
+ $this->functions->billing_email();
334
  }
335
 
336
  /**
337
  * Return/Show billing phone
338
  */
339
  public function get_billing_phone() {
340
+ return $this->functions->get_billing_phone();
 
 
 
 
 
 
 
341
  }
342
  public function billing_phone() {
343
+ $this->functions->billing_phone();
344
  }
345
 
346
  /**
347
  * Return/Show shipping address
348
  */
349
  public function get_shipping_address() {
350
+ return $this->functions->get_shipping_address();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
351
  }
352
  public function shipping_address() {
353
+ $this->functions->shipping_address();
354
  }
355
 
356
  /**
357
  * Return/Show a custom field
358
  */
359
  public function get_custom_field( $field_name ) {
360
+ return $this->functions->get_custom_field( $field_name );
 
 
 
 
 
 
 
361
  }
362
  public function custom_field( $field_name, $field_label = '', $display_empty = false ) {
363
+ $this->functions->custom_field( $field_name, $field_label, $display_empty );
 
 
 
 
 
 
 
 
364
  }
365
 
366
  /**
367
  * Return/Show order notes
368
  */
369
  public function get_order_notes( $filter = 'customer' ) {
370
+ return $this->functions->get_order_notes( $filter );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
371
  }
372
  public function order_notes( $filter = 'customer' ) {
373
+ $this->functions->order_notes( $filter );
 
 
 
 
 
 
 
 
 
374
  }
375
 
376
  /**
377
  * Return/Show the current date
378
  */
379
  public function get_current_date() {
380
+ return $this->functions->get_current_date();
381
  }
382
  public function current_date() {
383
+ $this->functions->current_date();
384
  }
385
 
386
  /**
387
  * Return/Show payment method
388
  */
389
  public function get_payment_method() {
390
+ return $this->functions->get_payment_method();
 
 
 
 
 
 
 
 
 
391
  }
392
  public function payment_method() {
393
+ $this->functions->payment_method();
394
  }
395
 
396
  /**
397
  * Return/Show shipping method
398
  */
399
  public function get_shipping_method() {
400
+ return $this->functions->get_shipping_method();
 
401
  }
402
  public function shipping_method() {
403
+ $this->functions->shipping_method();
404
  }
405
 
406
  /**
407
  * Return/Show order number
408
  */
409
  public function get_order_number() {
410
+ return $this->functions->get_order_number();
 
 
 
 
 
 
 
 
 
 
 
411
  }
412
  public function order_number() {
413
+ $this->functions->order_number();
414
  }
415
 
416
  /**
417
  * Return/Show invoice number
418
  */
419
  public function get_invoice_number() {
420
+ return $this->functions->get_invoice_number();
 
 
 
 
 
 
 
421
  }
422
  public function invoice_number() {
423
+ $this->functions->invoice_number();
424
  }
425
 
426
  /**
427
  * Return/Show the order date
428
  */
429
  public function get_order_date() {
430
+ return $this->functions->get_order_date();
 
 
 
 
 
 
 
 
431
  }
432
  public function order_date() {
433
+ $this->functions->order_date();
434
  }
435
 
436
  /**
437
  * Return/Show the invoice date
438
  */
439
  public function get_invoice_date() {
440
+ return $this->functions->get_invoice_date();
 
 
 
 
 
 
 
 
 
 
441
  }
442
  public function invoice_date() {
443
+ $this->functions->invoice_date();
444
  }
445
 
446
  /**
447
  * Return the order items
448
  */
449
  public function get_order_items() {
450
+ return $this->functions->get_order_items();
451
  }
452
 
453
  /**
454
  * Return/show product attribute
455
  */
456
  public function get_product_attribute( $attribute_name, $product ) {
457
+ return $this->functions->get_product_attribute( $attribute_name, $product );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
458
  }
459
  public function product_attribute( $attribute_name, $product ) {
460
+ $this->functions->product_attribute( $attribute_name, $product );
461
  }
462
 
463
 
465
  * Return the order totals listing
466
  */
467
  public function get_woocommerce_totals() {
468
+ return $this->functions->get_woocommerce_totals();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
469
  }
470
 
471
  /**
472
  * Return/show the order subtotal
473
  */
474
  public function get_order_subtotal( $tax = 'excl', $discount = 'incl' ) { // set $tax to 'incl' to include tax, same for $discount
475
+ return $this->functions->get_order_subtotal( $tax, $discount );
 
 
 
 
 
 
 
 
 
 
 
476
  }
477
  public function order_subtotal( $tax = 'excl', $discount = 'incl' ) {
478
+ $this->functions->order_subtotal( $tax, $discount );
 
479
  }
480
 
481
  /**
482
  * Return/show the order shipping costs
483
  */
484
  public function get_order_shipping( $tax = 'excl' ) { // set $tax to 'incl' to include tax
485
+ return $this->functions->get_order_shipping( $tax );
 
 
 
 
 
 
 
 
 
 
 
486
  }
487
  public function order_shipping( $tax = 'excl' ) {
488
+ $this->functions->order_shipping( $tax );
 
489
  }
490
 
491
  /**
492
  * Return/show the total discount
493
  */
494
  public function get_order_discount( $type = 'total', $tax = 'incl' ) {
495
+ return $this->functions->get_order_discount( $type, $tax );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
496
  }
497
  public function order_discount( $type = 'total', $tax = 'incl' ) {
498
+ $this->functions->order_discount( $type, $tax );
 
499
  }
500
 
501
  /**
502
  * Return the order fees
503
  */
504
  public function get_order_fees( $tax = 'excl' ) {
505
+ return $this->functions->get_order_fees( $tax );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
506
  }
507
 
508
  /**
509
  * Return the order taxes
510
  */
511
  public function get_order_taxes() {
512
+ return $this->functions->get_order_taxes();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
513
  }
514
 
515
  /**
516
  * Return/show the order grand total
517
  */
518
  public function get_order_grand_total( $tax = 'incl' ) {
519
+ return $this->functions->get_order_grand_total( $tax );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
520
  }
521
  public function order_grand_total( $tax = 'incl' ) {
522
+ $this->functions->order_grand_total( $tax );
 
523
  }
524
 
525
 
527
  * Return/Show shipping notes
528
  */
529
  public function get_shipping_notes() {
530
+ return $this->functions->get_shipping_notes();
 
531
  }
532
  public function shipping_notes() {
533
+ $this->functions->shipping_notes();
534
  }
535
 
536
 
538
  * Return/Show shop/company footer imprint, copyright etc.
539
  */
540
  public function get_footer() {
541
+ return $this->functions->get_footer();
 
 
 
542
  }
543
  public function footer() {
544
+ $this->functions->footer();
545
  }
546
 
547
  /**
548
  * Return/Show Extra field 1
549
  */
550
  public function get_extra_1() {
551
+ return $this->functions->get_extra_1();
 
 
 
552
  }
553
  public function extra_1() {
554
+ $this->functions->extra_1();
555
  }
556
 
557
  /**
558
  * Return/Show Extra field 2
559
  */
560
  public function get_extra_2() {
561
+ return $this->functions->get_extra_2();
 
 
 
562
  }
563
  public function extra_2() {
564
+ $this->functions->extra_2();
565
  }
566
 
567
+ /**
568
  * Return/Show Extra field 3
569
  */
570
  public function get_extra_3() {
571
+ return $this->functions->get_extra_3();
 
 
 
572
  }
573
  public function extra_3() {
574
+ $this->functions->extra_3();
575
+ }
576
  }
577
  }
578
 
579
+ /**
580
+ * Returns the main instance of WooCommerce PDF Invoices & Packing Slips to prevent the need to use globals.
581
+ *
582
+ * @since 1.6
583
+ * @return WPO_WCPDF
584
+ */
585
+ function WPO_WCPDF() {
586
+ return WooCommerce_PDF_Invoices::instance();
587
+ }
588
+
589
+ // Global for backwards compatibility.
590
+ $GLOBALS['wpo_wcpdf'] = WPO_WCPDF();