Version Description
- New: Add per-order notes to invoices (requires template update if you have a custom template)
- New: Show notice with instructions for protecting the invoice folder on NGINX setups
- Fix: Show correct "next number" on settings page for sites using MySQL 8+
- Tested up to WooCommerce 4.6
Download this release
Release Info
Developer | pomegranate |
Plugin | WooCommerce PDF Invoices & Packing Slips |
Version | 2.7.0 |
Comparing to | |
See all releases |
Code changes from version 2.6.1 to 2.7.0
- assets/css/order-styles.css +5 -3
- assets/images/nginx.svg +3 -0
- assets/js/order-script.js +11 -4
- includes/class-wcpdf-admin.php +71 -0
- includes/documents/abstract-wcpdf-order-document-methods.php +12 -0
- includes/documents/abstract-wcpdf-order-document.php +28 -0
- includes/documents/class-wcpdf-sequential-number-store.php +178 -174
- includes/views/wcpdf-extensions.php +2 -2
- includes/views/wcpdf-settings-page.php +52 -52
- readme.txt +7 -1
- templates/Simple/invoice.php +8 -0
- templates/Simple/style.css +1 -0
- woocommerce-pdf-invoices-packingslips.php +33 -3
assets/css/order-styles.css
CHANGED
@@ -64,18 +64,20 @@
|
|
64 |
|
65 |
/* Edit buttons Invoice, Proforma and Credit */
|
66 |
.wcpdf-data-fields h4 .dashicons:first-of-type {
|
67 |
-
margin-left:20px!important;
|
68 |
}
|
69 |
|
70 |
.wcpdf-data-fields .wpo-wcpdf-edit-date-number,
|
71 |
.wcpdf-data-fields .wpo-wcpdf-delete-document,
|
72 |
-
.wcpdf-data-fields .wpo-wcpdf-regenerate-document
|
|
|
73 |
opacity:0.5;
|
74 |
}
|
75 |
|
76 |
.wcpdf-data-fields .wpo-wcpdf-edit-date-number:hover,
|
77 |
.wcpdf-data-fields .wpo-wcpdf-delete-document:hover,
|
78 |
-
.wcpdf-data-fields .wpo-wcpdf-regenerate-document:hover
|
|
|
79 |
opacity:1;
|
80 |
cursor:pointer;
|
81 |
}
|
64 |
|
65 |
/* Edit buttons Invoice, Proforma and Credit */
|
66 |
.wcpdf-data-fields h4 .dashicons:first-of-type {
|
67 |
+
margin-left:20px !important;
|
68 |
}
|
69 |
|
70 |
.wcpdf-data-fields .wpo-wcpdf-edit-date-number,
|
71 |
.wcpdf-data-fields .wpo-wcpdf-delete-document,
|
72 |
+
.wcpdf-data-fields .wpo-wcpdf-regenerate-document,
|
73 |
+
.wcpdf-data-fields .wpo-wcpdf-edit-document-notes {
|
74 |
opacity:0.5;
|
75 |
}
|
76 |
|
77 |
.wcpdf-data-fields .wpo-wcpdf-edit-date-number:hover,
|
78 |
.wcpdf-data-fields .wpo-wcpdf-delete-document:hover,
|
79 |
+
.wcpdf-data-fields .wpo-wcpdf-regenerate-document:hover,
|
80 |
+
.wcpdf-data-fields .wpo-wcpdf-edit-document-notes:hover {
|
81 |
opacity:1;
|
82 |
cursor:pointer;
|
83 |
}
|
assets/images/nginx.svg
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
1 |
+
<svg width="97" height="21" viewBox="0 0 97 21" fill="none" xmlns="http://www.w3.org/2000/svg">
|
2 |
+
<path d="M18.7764 20.6272C18.2368 20.6272 17.7113 20.4189 17.309 20.0213L5.06764 7.77995V18.5112C5.06764 19.6473 4.13983 20.5799 2.99901 20.5799C1.85819 20.5799 0.930389 19.7041 0.930389 18.5112V2.79537C0.930389 1.95751 1.43689 1.20485 2.20849 0.882961C2.98008 0.56107 3.86528 0.74095 4.46172 1.33266L16.7031 13.574V2.79537C16.7031 1.65929 17.6309 0.72675 18.7717 0.72675C19.9125 0.72675 20.8403 1.65455 20.8403 2.79537V18.5112C20.8403 19.6473 19.9125 20.5799 18.7717 20.5799L18.7764 20.6272ZM28.3479 0.698347L27.7799 1.75869L23.3776 9.74917L22.8095 10.7574L23.3776 11.7657L27.7799 19.4958L28.3716 20.5562H39.8745L40.4425 19.3917L43.7277 12.774L45.1951 9.77284H41.8626L33.4603 9.7965C32.3716 9.7823 31.3633 10.7716 31.3633 11.8651C31.3633 12.9586 32.3668 13.948 33.4603 13.9338L38.5254 13.9101L37.2851 16.4189H30.7811L27.5479 10.729L30.8047 4.83559H37.7348L39.3443 8.14918H43.5099L40.8875 1.86283L40.3194 0.698347H28.3432H28.3479ZM49.2945 0.674678C48.2058 0.688879 47.2401 1.68769 47.259 2.76697V8.16338H51.3963V2.76697C51.4105 1.66875 50.4495 0.660477 49.304 0.674678H49.2945ZM55.9312 20.6272C54.7951 20.6272 53.8625 19.6994 53.8625 18.5586V2.82851C53.8625 1.69242 54.7903 0.759885 55.9312 0.759885C57.072 0.759885 57.9998 1.68769 57.9998 2.82851V13.6071L70.2411 1.3658C70.8328 0.774085 71.7228 0.59894 72.4943 0.916097C73.2659 1.23325 73.7724 1.99064 73.7724 2.82851V18.6059C73.7724 19.742 72.8446 20.6745 71.7038 20.6745C70.563 20.6745 69.6352 19.7467 69.6352 18.6059V7.82255L57.3939 20.0639C57.0057 20.452 56.4803 20.6698 55.9264 20.6698L55.9312 20.6272ZM89.0859 10.7006L95.5238 4.29122C96.3285 3.48649 96.3285 2.17526 95.5285 1.3658C94.7285 0.556336 93.4125 0.56107 92.6031 1.36106L86.1653 7.78468L79.7274 1.36106C78.9227 0.556336 77.6067 0.556336 76.802 1.3658C75.9973 2.17526 75.9973 3.48649 76.8067 4.29122L83.2446 10.7006L76.8115 17.0911C76.0068 17.8959 76.0067 19.2071 76.8067 20.0165C77.1949 20.4094 77.7203 20.6319 78.2269 20.6319C78.7334 20.6319 79.2825 20.4331 79.6848 20.026L86.1084 13.6213L92.5321 20.026C92.9202 20.4142 93.4457 20.6319 93.99 20.6319C94.5344 20.6319 95.0504 20.4284 95.4101 20.0165C96.2149 19.2118 96.2149 17.9006 95.4054 17.0911L88.9913 10.7006H89.0859ZM49.1999 20.613C48.1111 20.5988 47.1454 19.6 47.1644 18.5207V9.85804H51.3016V18.5112C51.3158 19.6094 50.3549 20.6177 49.2093 20.6035" fill="#009900"/>
|
3 |
+
</svg>
|
assets/js/order-script.js
CHANGED
@@ -32,11 +32,18 @@ jQuery(document).ready(function($) {
|
|
32 |
$('#wpo_wcpdf-data-input-box').insertAfter('#woocommerce-order-data');
|
33 |
|
34 |
// enable invoice number edit if user initiated
|
35 |
-
$( ".wpo-wcpdf-set-date-number, .wpo-wcpdf-edit-date-number" ).click(function() {
|
36 |
$form = $(this).closest('.wcpdf-data-fields');
|
37 |
-
|
38 |
-
$form.find(".
|
39 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
});
|
41 |
|
42 |
$( ".wcpdf-data-fields .wpo-wcpdf-delete-document" ).click(function() {
|
32 |
$('#wpo_wcpdf-data-input-box').insertAfter('#woocommerce-order-data');
|
33 |
|
34 |
// enable invoice number edit if user initiated
|
35 |
+
$( ".wpo-wcpdf-set-date-number, .wpo-wcpdf-edit-date-number, .wpo-wcpdf-edit-document-notes" ).click(function() {
|
36 |
$form = $(this).closest('.wcpdf-data-fields');
|
37 |
+
// check visibility
|
38 |
+
if( $form.find(".read-only").is(":visible") ) {
|
39 |
+
$form.find(".read-only").hide();
|
40 |
+
$form.find(".editable").show();
|
41 |
+
$form.find(':input').prop('disabled', false);
|
42 |
+
} else {
|
43 |
+
$form.find(".read-only").show();
|
44 |
+
$form.find(".editable").hide();
|
45 |
+
$form.find(':input').prop('disabled', true);
|
46 |
+
}
|
47 |
});
|
48 |
|
49 |
$( ".wcpdf-data-fields .wpo-wcpdf-delete-document" ).click(function() {
|
includes/class-wcpdf-admin.php
CHANGED
@@ -372,7 +372,10 @@ class Admin {
|
|
372 |
if ( $invoice = wcpdf_get_invoice( $order ) ) {
|
373 |
$invoice_number = $invoice->get_number();
|
374 |
$invoice_date = $invoice->get_date();
|
|
|
|
|
375 |
?>
|
|
|
376 |
<div class="wcpdf-data-fields" data-document="invoice" data-order_id="<?php echo WCX_Order::get_id( $order ); ?>">
|
377 |
<h4>
|
378 |
<?php echo $invoice->get_title(); ?><?php if ($invoice->exists()) : ?>
|
@@ -430,6 +433,38 @@ class Admin {
|
|
430 |
</p>
|
431 |
</div>
|
432 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
433 |
<?php
|
434 |
}
|
435 |
|
@@ -522,6 +557,42 @@ class Admin {
|
|
522 |
$invoice->set_number( $invoice_number );
|
523 |
}
|
524 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
525 |
$invoice->save();
|
526 |
}
|
527 |
}
|
372 |
if ( $invoice = wcpdf_get_invoice( $order ) ) {
|
373 |
$invoice_number = $invoice->get_number();
|
374 |
$invoice_date = $invoice->get_date();
|
375 |
+
$invoice_notes = !empty($invoice->get_document_notes()) ? $invoice->get_document_notes() : null;
|
376 |
+
|
377 |
?>
|
378 |
+
|
379 |
<div class="wcpdf-data-fields" data-document="invoice" data-order_id="<?php echo WCX_Order::get_id( $order ); ?>">
|
380 |
<h4>
|
381 |
<?php echo $invoice->get_title(); ?><?php if ($invoice->exists()) : ?>
|
433 |
</p>
|
434 |
</div>
|
435 |
</div>
|
436 |
+
|
437 |
+
<?php do_action( 'wpo_wcpdf_meta_box_before_document_notes', $invoice, $order ); ?>
|
438 |
+
|
439 |
+
<div class="wcpdf-data-fields" data-document="invoice" data-order_id="<?php echo WCX_Order::get_id( $order ); ?>">
|
440 |
+
<div class="invoice-notes">
|
441 |
+
<p class="form-field form-field-wide">
|
442 |
+
<div>
|
443 |
+
<span><strong><?php _e( 'Notes (printed in the invoice):', 'woocommerce-pdf-invoices-packing-slips' ); ?></strong></span>
|
444 |
+
<span class="wpo-wcpdf-edit-document-notes dashicons dashicons-edit"></span>
|
445 |
+
</div>
|
446 |
+
<!-- Read only -->
|
447 |
+
<div class="read-only">
|
448 |
+
<?php if ( $invoice->exists() ) : ?>
|
449 |
+
<p><?php if (!empty($invoice_notes)) echo $invoice_notes; ?></p>
|
450 |
+
<?php endif; ?>
|
451 |
+
</div>
|
452 |
+
<!-- Editable -->
|
453 |
+
<div class="editable">
|
454 |
+
<p class="form-field form-field-wide">
|
455 |
+
<?php if ( $invoice->exists() ) : ?>
|
456 |
+
<p><textarea name="wcpdf_invoice_notes" cols="60" rows="5" disabled="disabled"><?php if (!empty($invoice_notes)) echo $invoice_notes; ?></textarea></p>
|
457 |
+
<?php else : ?>
|
458 |
+
<p><textarea name="wcpdf_invoice_notes" cols="60" rows="5" disabled="disabled"></textarea></p>
|
459 |
+
<?php endif; ?>
|
460 |
+
</p>
|
461 |
+
</div>
|
462 |
+
</p>
|
463 |
+
</div>
|
464 |
+
</div>
|
465 |
+
|
466 |
+
<?php do_action( 'wpo_wcpdf_meta_box_after_document_notes', $invoice, $order ); ?>
|
467 |
+
|
468 |
<?php
|
469 |
}
|
470 |
|
557 |
$invoice->set_number( $invoice_number );
|
558 |
}
|
559 |
|
560 |
+
if ( isset( $_POST['wcpdf_invoice_notes'] ) ) {
|
561 |
+
// allowed HTML
|
562 |
+
$allowed_html = array(
|
563 |
+
'a' => array(
|
564 |
+
'href' => array(),
|
565 |
+
'title' => array(),
|
566 |
+
'id' => array(),
|
567 |
+
'class' => array(),
|
568 |
+
'style' => array(),
|
569 |
+
),
|
570 |
+
'br' => array(),
|
571 |
+
'em' => array(),
|
572 |
+
'strong'=> array(),
|
573 |
+
'div' => array(
|
574 |
+
'id' => array(),
|
575 |
+
'class' => array(),
|
576 |
+
'style' => array(),
|
577 |
+
),
|
578 |
+
'span' => array(
|
579 |
+
'id' => array(),
|
580 |
+
'class' => array(),
|
581 |
+
'style' => array(),
|
582 |
+
),
|
583 |
+
'p' => array(
|
584 |
+
'id' => array(),
|
585 |
+
'class' => array(),
|
586 |
+
'style' => array(),
|
587 |
+
),
|
588 |
+
'b' => array(),
|
589 |
+
);
|
590 |
+
// sanitize
|
591 |
+
$invoice_notes = wp_kses( stripslashes($_POST['wcpdf_invoice_notes']), $allowed_html );
|
592 |
+
// set notes
|
593 |
+
$invoice->set_notes( $invoice_notes );
|
594 |
+
}
|
595 |
+
|
596 |
$invoice->save();
|
597 |
}
|
598 |
}
|
includes/documents/abstract-wcpdf-order-document-methods.php
CHANGED
@@ -1207,6 +1207,18 @@ abstract class Order_Document_Methods extends Order_Document {
|
|
1207 |
echo $this->get_invoice_date();
|
1208 |
}
|
1209 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1210 |
|
1211 |
}
|
1212 |
|
1207 |
echo $this->get_invoice_date();
|
1208 |
}
|
1209 |
|
1210 |
+
public function get_document_notes() {
|
1211 |
+
if ( $document_notes = $this->get_notes( $this->get_type() ) ) {
|
1212 |
+
return $document_notes;
|
1213 |
+
} else {
|
1214 |
+
return '';
|
1215 |
+
}
|
1216 |
+
}
|
1217 |
+
|
1218 |
+
public function document_notes() {
|
1219 |
+
echo $this->get_document_notes();
|
1220 |
+
}
|
1221 |
+
|
1222 |
|
1223 |
}
|
1224 |
|
includes/documents/abstract-wcpdf-order-document.php
CHANGED
@@ -227,6 +227,7 @@ abstract class Order_Document {
|
|
227 |
// always load date before number, because date is used in number formatting
|
228 |
'date' => WCX_Order::get_meta( $order, "_wcpdf_{$this->slug}_date", true ),
|
229 |
'number' => $number,
|
|
|
230 |
), $order );
|
231 |
|
232 |
return;
|
@@ -260,6 +261,8 @@ abstract class Order_Document {
|
|
260 |
WCX_Order::delete_meta_data( $order, "_wcpdf_{$this->slug}_{$key}_data" );
|
261 |
// deleting the number = deleting the document, so also delete document settings
|
262 |
WCX_Order::delete_meta_data( $order, "_wcpdf_{$this->slug}_settings" );
|
|
|
|
|
263 |
}
|
264 |
} else {
|
265 |
if ( $key == 'date' ) {
|
@@ -270,6 +273,9 @@ abstract class Order_Document {
|
|
270 |
// store both formatted number and number data
|
271 |
WCX_Order::update_meta_data( $order, "_wcpdf_{$this->slug}_{$key}", $value->formatted_number );
|
272 |
WCX_Order::update_meta_data( $order, "_wcpdf_{$this->slug}_{$key}_data", $value->to_array() );
|
|
|
|
|
|
|
273 |
}
|
274 |
}
|
275 |
}
|
@@ -289,6 +295,7 @@ abstract class Order_Document {
|
|
289 |
'date_formatted',
|
290 |
'number',
|
291 |
'number_data',
|
|
|
292 |
), $this );
|
293 |
foreach ($data_to_remove as $data_key) {
|
294 |
WCX_Order::delete_meta_data( $order, "_wcpdf_{$this->slug}_{$data_key}" );
|
@@ -396,6 +403,10 @@ abstract class Order_Document {
|
|
396 |
return $this->get_data( 'date', $document_type, $order, $context );
|
397 |
}
|
398 |
|
|
|
|
|
|
|
|
|
399 |
public function get_title() {
|
400 |
return apply_filters( "wpo_wcpdf_{$this->slug}_title", $this->title, $this );
|
401 |
}
|
@@ -487,6 +498,23 @@ abstract class Order_Document {
|
|
487 |
$this->data[ 'number' ] = $document_number;
|
488 |
}
|
489 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
490 |
/*
|
491 |
|--------------------------------------------------------------------------
|
492 |
| Settings getters / outputters
|
227 |
// always load date before number, because date is used in number formatting
|
228 |
'date' => WCX_Order::get_meta( $order, "_wcpdf_{$this->slug}_date", true ),
|
229 |
'number' => $number,
|
230 |
+
'notes' => WCX_Order::get_meta( $order, "_wcpdf_{$this->slug}_notes", true ),
|
231 |
), $order );
|
232 |
|
233 |
return;
|
261 |
WCX_Order::delete_meta_data( $order, "_wcpdf_{$this->slug}_{$key}_data" );
|
262 |
// deleting the number = deleting the document, so also delete document settings
|
263 |
WCX_Order::delete_meta_data( $order, "_wcpdf_{$this->slug}_settings" );
|
264 |
+
} elseif ( $key == 'notes' ) {
|
265 |
+
WCX_Order::delete_meta_data( $order, "_wcpdf_{$this->slug}_{$key}" );
|
266 |
}
|
267 |
} else {
|
268 |
if ( $key == 'date' ) {
|
273 |
// store both formatted number and number data
|
274 |
WCX_Order::update_meta_data( $order, "_wcpdf_{$this->slug}_{$key}", $value->formatted_number );
|
275 |
WCX_Order::update_meta_data( $order, "_wcpdf_{$this->slug}_{$key}_data", $value->to_array() );
|
276 |
+
} elseif ( $key == 'notes' ) {
|
277 |
+
// store notes
|
278 |
+
WCX_Order::update_meta_data( $order, "_wcpdf_{$this->slug}_{$key}", $value );
|
279 |
}
|
280 |
}
|
281 |
}
|
295 |
'date_formatted',
|
296 |
'number',
|
297 |
'number_data',
|
298 |
+
'notes',
|
299 |
), $this );
|
300 |
foreach ($data_to_remove as $data_key) {
|
301 |
WCX_Order::delete_meta_data( $order, "_wcpdf_{$this->slug}_{$data_key}" );
|
403 |
return $this->get_data( 'date', $document_type, $order, $context );
|
404 |
}
|
405 |
|
406 |
+
public function get_notes( $document_type = '', $order = null, $context = 'view' ) {
|
407 |
+
return $this->get_data( 'notes', $document_type, $order, $context );
|
408 |
+
}
|
409 |
+
|
410 |
public function get_title() {
|
411 |
return apply_filters( "wpo_wcpdf_{$this->slug}_title", $this->title, $this );
|
412 |
}
|
498 |
$this->data[ 'number' ] = $document_number;
|
499 |
}
|
500 |
|
501 |
+
public function set_notes( $value, $order = null ) {
|
502 |
+
$order = empty( $order ) ? $this->order : $order;
|
503 |
+
|
504 |
+
try {
|
505 |
+
if ( empty( $value ) ) {
|
506 |
+
$this->data[ 'notes' ] = null;
|
507 |
+
return;
|
508 |
+
}
|
509 |
+
|
510 |
+
$this->data[ 'notes' ] = $value;
|
511 |
+
} catch ( \Exception $e ) {
|
512 |
+
wcpdf_log_error( $e->getMessage() );
|
513 |
+
} catch ( \Error $e ) {
|
514 |
+
wcpdf_log_error( $e->getMessage() );
|
515 |
+
}
|
516 |
+
}
|
517 |
+
|
518 |
/*
|
519 |
|--------------------------------------------------------------------------
|
520 |
| Settings getters / outputters
|
includes/documents/class-wcpdf-sequential-number-store.php
CHANGED
@@ -1,174 +1,178 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WPO\WC\PDF_Invoices\Documents;
|
3 |
-
|
4 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
5 |
-
exit; // Exit if accessed directly
|
6 |
-
}
|
7 |
-
|
8 |
-
if ( !class_exists( '\\WPO\\WC\\PDF_Invoices\\Documents\\Sequential_Number_Store' ) ) :
|
9 |
-
|
10 |
-
/**
|
11 |
-
* Class handling database interaction for sequential numbers
|
12 |
-
*
|
13 |
-
* @class \WPO\WC\PDF_Invoices\Documents\Sequential_Number_Store
|
14 |
-
* @version 2.0
|
15 |
-
* @category Class
|
16 |
-
* @author Ewout Fernhout
|
17 |
-
*/
|
18 |
-
|
19 |
-
class Sequential_Number_Store {
|
20 |
-
/**
|
21 |
-
* Name of the number store (used for table_name)
|
22 |
-
* @var String
|
23 |
-
*/
|
24 |
-
public $store_name;
|
25 |
-
|
26 |
-
/**
|
27 |
-
* Number store method, either 'auto_increment' or 'calculate'
|
28 |
-
* @var String
|
29 |
-
*/
|
30 |
-
public $method;
|
31 |
-
|
32 |
-
/**
|
33 |
-
* Name of the table that stores the number sequence (including the wp_wcpdf_ table prefix)
|
34 |
-
* @var String
|
35 |
-
*/
|
36 |
-
public $table_name;
|
37 |
-
|
38 |
-
public function __construct( $store_name, $method = 'auto_increment' ) {
|
39 |
-
global $wpdb;
|
40 |
-
$this->store_name = $store_name;
|
41 |
-
$this->method = $method;
|
42 |
-
$this->table_name = apply_filters( "wpo_wcpdf_number_store_table_name", "{$wpdb->prefix}wcpdf_{$store_name}", $store_name, $method ); // i.e. wp_wcpdf_invoice_number
|
43 |
-
|
44 |
-
$this->init();
|
45 |
-
}
|
46 |
-
|
47 |
-
public function init() {
|
48 |
-
global $wpdb;
|
49 |
-
// check if table exists
|
50 |
-
if( $wpdb->get_var("SHOW TABLES LIKE '{$this->table_name}'") == $this->table_name) {
|
51 |
-
// check calculated_number column if using 'calculate' method
|
52 |
-
if ( $this->method == 'calculate' ) {
|
53 |
-
$column_exists = $wpdb->get_var("SHOW COLUMNS FROM `{$this->table_name}` LIKE 'calculated_number'");
|
54 |
-
if (empty($column_exists)) {
|
55 |
-
$wpdb->query("ALTER TABLE {$this->table_name} ADD calculated_number int (16)");
|
56 |
-
}
|
57 |
-
}
|
58 |
-
return; // no further business
|
59 |
-
}
|
60 |
-
|
61 |
-
// create table (in case of concurrent requests, this does no harm if it already exists)
|
62 |
-
$charset_collate = $wpdb->get_charset_collate();
|
63 |
-
// dbDelta is a sensitive kid, so we omit indentation
|
64 |
-
$sql = "CREATE TABLE {$this->table_name} (
|
65 |
-
id int(16) NOT NULL AUTO_INCREMENT,
|
66 |
-
order_id int(16),
|
67 |
-
date datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
|
68 |
-
calculated_number int (16),
|
69 |
-
PRIMARY KEY (id)
|
70 |
-
) $charset_collate;";
|
71 |
-
|
72 |
-
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
|
73 |
-
$result = dbDelta( $sql );
|
74 |
-
|
75 |
-
return $result;
|
76 |
-
}
|
77 |
-
|
78 |
-
/**
|
79 |
-
* Consume/create the next number and return it
|
80 |
-
* @param integer $order_id WooCommerce Order ID
|
81 |
-
* @param string $date Local date, formatted as Y-m-d H:i:s
|
82 |
-
* @return int Number that was consumed/created
|
83 |
-
*/
|
84 |
-
public function increment( $order_id = 0, $date = null ) {
|
85 |
-
global $wpdb;
|
86 |
-
if ( empty( $date ) ) {
|
87 |
-
$date = get_date_from_gmt( date( 'Y-m-d H:i:s' ) );
|
88 |
-
}
|
89 |
-
|
90 |
-
do_action( 'wpo_wcpdf_before_sequential_number_increment', $this, $order_id, $date );
|
91 |
-
|
92 |
-
$data = array(
|
93 |
-
'order_id' => (int) $order_id,
|
94 |
-
'date' => $date,
|
95 |
-
);
|
96 |
-
|
97 |
-
if ( $this->method == 'auto_increment' ) {
|
98 |
-
$wpdb->insert( $this->table_name, $data );
|
99 |
-
$number = $wpdb->insert_id;
|
100 |
-
} elseif ( $this->method == 'calculate' ) {
|
101 |
-
$number = $data['calculated_number'] = $this->get_next();
|
102 |
-
$wpdb->insert( $this->table_name, $data );
|
103 |
-
}
|
104 |
-
|
105 |
-
// return generated number
|
106 |
-
return $number;
|
107 |
-
}
|
108 |
-
|
109 |
-
/**
|
110 |
-
* Get the number that will be used on the next increment
|
111 |
-
* @return int next number
|
112 |
-
*/
|
113 |
-
public function get_next() {
|
114 |
-
global $wpdb;
|
115 |
-
if ( $this->method == 'auto_increment' ) {
|
116 |
-
//
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
$next =
|
127 |
-
}
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
);
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace WPO\WC\PDF_Invoices\Documents;
|
3 |
+
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
5 |
+
exit; // Exit if accessed directly
|
6 |
+
}
|
7 |
+
|
8 |
+
if ( !class_exists( '\\WPO\\WC\\PDF_Invoices\\Documents\\Sequential_Number_Store' ) ) :
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Class handling database interaction for sequential numbers
|
12 |
+
*
|
13 |
+
* @class \WPO\WC\PDF_Invoices\Documents\Sequential_Number_Store
|
14 |
+
* @version 2.0
|
15 |
+
* @category Class
|
16 |
+
* @author Ewout Fernhout
|
17 |
+
*/
|
18 |
+
|
19 |
+
class Sequential_Number_Store {
|
20 |
+
/**
|
21 |
+
* Name of the number store (used for table_name)
|
22 |
+
* @var String
|
23 |
+
*/
|
24 |
+
public $store_name;
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Number store method, either 'auto_increment' or 'calculate'
|
28 |
+
* @var String
|
29 |
+
*/
|
30 |
+
public $method;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Name of the table that stores the number sequence (including the wp_wcpdf_ table prefix)
|
34 |
+
* @var String
|
35 |
+
*/
|
36 |
+
public $table_name;
|
37 |
+
|
38 |
+
public function __construct( $store_name, $method = 'auto_increment' ) {
|
39 |
+
global $wpdb;
|
40 |
+
$this->store_name = $store_name;
|
41 |
+
$this->method = $method;
|
42 |
+
$this->table_name = apply_filters( "wpo_wcpdf_number_store_table_name", "{$wpdb->prefix}wcpdf_{$store_name}", $store_name, $method ); // i.e. wp_wcpdf_invoice_number
|
43 |
+
|
44 |
+
$this->init();
|
45 |
+
}
|
46 |
+
|
47 |
+
public function init() {
|
48 |
+
global $wpdb;
|
49 |
+
// check if table exists
|
50 |
+
if( $wpdb->get_var("SHOW TABLES LIKE '{$this->table_name}'") == $this->table_name) {
|
51 |
+
// check calculated_number column if using 'calculate' method
|
52 |
+
if ( $this->method == 'calculate' ) {
|
53 |
+
$column_exists = $wpdb->get_var("SHOW COLUMNS FROM `{$this->table_name}` LIKE 'calculated_number'");
|
54 |
+
if (empty($column_exists)) {
|
55 |
+
$wpdb->query("ALTER TABLE {$this->table_name} ADD calculated_number int (16)");
|
56 |
+
}
|
57 |
+
}
|
58 |
+
return; // no further business
|
59 |
+
}
|
60 |
+
|
61 |
+
// create table (in case of concurrent requests, this does no harm if it already exists)
|
62 |
+
$charset_collate = $wpdb->get_charset_collate();
|
63 |
+
// dbDelta is a sensitive kid, so we omit indentation
|
64 |
+
$sql = "CREATE TABLE {$this->table_name} (
|
65 |
+
id int(16) NOT NULL AUTO_INCREMENT,
|
66 |
+
order_id int(16),
|
67 |
+
date datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
|
68 |
+
calculated_number int (16),
|
69 |
+
PRIMARY KEY (id)
|
70 |
+
) $charset_collate;";
|
71 |
+
|
72 |
+
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
|
73 |
+
$result = dbDelta( $sql );
|
74 |
+
|
75 |
+
return $result;
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Consume/create the next number and return it
|
80 |
+
* @param integer $order_id WooCommerce Order ID
|
81 |
+
* @param string $date Local date, formatted as Y-m-d H:i:s
|
82 |
+
* @return int Number that was consumed/created
|
83 |
+
*/
|
84 |
+
public function increment( $order_id = 0, $date = null ) {
|
85 |
+
global $wpdb;
|
86 |
+
if ( empty( $date ) ) {
|
87 |
+
$date = get_date_from_gmt( date( 'Y-m-d H:i:s' ) );
|
88 |
+
}
|
89 |
+
|
90 |
+
do_action( 'wpo_wcpdf_before_sequential_number_increment', $this, $order_id, $date );
|
91 |
+
|
92 |
+
$data = array(
|
93 |
+
'order_id' => (int) $order_id,
|
94 |
+
'date' => $date,
|
95 |
+
);
|
96 |
+
|
97 |
+
if ( $this->method == 'auto_increment' ) {
|
98 |
+
$wpdb->insert( $this->table_name, $data );
|
99 |
+
$number = $wpdb->insert_id;
|
100 |
+
} elseif ( $this->method == 'calculate' ) {
|
101 |
+
$number = $data['calculated_number'] = $this->get_next();
|
102 |
+
$wpdb->insert( $this->table_name, $data );
|
103 |
+
}
|
104 |
+
|
105 |
+
// return generated number
|
106 |
+
return $number;
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Get the number that will be used on the next increment
|
111 |
+
* @return int next number
|
112 |
+
*/
|
113 |
+
public function get_next() {
|
114 |
+
global $wpdb;
|
115 |
+
if ( $this->method == 'auto_increment' ) {
|
116 |
+
// clear cache first on mysql 8.0+
|
117 |
+
if ( $wpdb->get_var( "SHOW VARIABLES LIKE 'information_schema_stats_expiry'" ) ) {
|
118 |
+
$wpdb->query( "SET SESSION information_schema_stats_expiry = 0" );
|
119 |
+
}
|
120 |
+
// get next auto_increment value
|
121 |
+
$table_status = $wpdb->get_row("SHOW TABLE STATUS LIKE '{$this->table_name}'");
|
122 |
+
$next = $table_status->Auto_increment;
|
123 |
+
} elseif ( $this->method == 'calculate' ) {
|
124 |
+
$last_row = $wpdb->get_row( "SELECT * FROM {$this->table_name} WHERE id = ( SELECT MAX(id) from {$this->table_name} )" );
|
125 |
+
if ( empty( $last_row ) ) {
|
126 |
+
$next = 1;
|
127 |
+
} elseif ( !empty( $last_row->calculated_number ) ) {
|
128 |
+
$next = (int) $last_row->calculated_number + 1;
|
129 |
+
} else {
|
130 |
+
$next = (int) $last_row->id + 1;
|
131 |
+
}
|
132 |
+
}
|
133 |
+
return $next;
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Set the number that will be used on the next increment
|
138 |
+
*/
|
139 |
+
public function set_next( $number = 1 ) {
|
140 |
+
global $wpdb;
|
141 |
+
|
142 |
+
// delete all rows
|
143 |
+
$delete = $wpdb->query("TRUNCATE TABLE {$this->table_name}");
|
144 |
+
|
145 |
+
// set auto_increment
|
146 |
+
if ( $number > 1 ) {
|
147 |
+
// if AUTO_INCREMENT is not 1, we need to make sure we have a 'highest value' in case of server restarts
|
148 |
+
// https://serverfault.com/questions/228690/mysql-auto-increment-fields-resets-by-itself
|
149 |
+
$highest_number = (int) $number - 1;
|
150 |
+
$wpdb->query( $wpdb->prepare( "ALTER TABLE {$this->table_name} AUTO_INCREMENT=%d;", $highest_number ) );
|
151 |
+
$data = array(
|
152 |
+
'order_id' => 0,
|
153 |
+
'date' => get_date_from_gmt( date( 'Y-m-d H:i:s' ) ),
|
154 |
+
);
|
155 |
+
|
156 |
+
if ( $this->method == 'calculate' ) {
|
157 |
+
$data['calculated_number'] = $highest_number;
|
158 |
+
}
|
159 |
+
|
160 |
+
// after this insert, AUTO_INCREMENT will be equal to $number
|
161 |
+
$wpdb->insert( $this->table_name, $data );
|
162 |
+
} else {
|
163 |
+
// simple scenario, no need to insert any rows
|
164 |
+
$wpdb->query( $wpdb->prepare( "ALTER TABLE {$this->table_name} AUTO_INCREMENT=%d;", $number ) );
|
165 |
+
}
|
166 |
+
}
|
167 |
+
|
168 |
+
public function get_last_date( $format = 'Y-m-d H:i:s' ) {
|
169 |
+
global $wpdb;
|
170 |
+
$row = $wpdb->get_row( "SELECT * FROM {$this->table_name} WHERE id = ( SELECT MAX(id) from {$this->table_name} )" );
|
171 |
+
$date = isset( $row->date ) ? $row->date : 'now';
|
172 |
+
$formatted_date = date( $format, strtotime( $date ) );
|
173 |
+
|
174 |
+
return $formatted_date;
|
175 |
+
}
|
176 |
+
}
|
177 |
+
|
178 |
+
endif; // class_exists
|
includes/views/wcpdf-extensions.php
CHANGED
@@ -11,7 +11,7 @@ jQuery(document).ready(function() {
|
|
11 |
</script>
|
12 |
|
13 |
<div class="wcpdf-extensions-ad">
|
14 |
-
<?php $no_pro = !class_exists('WooCommerce_PDF_IPS_Pro') && !class_exists('
|
15 |
<img src="<?php echo WPO_WCPDF()->plugin_url() . '/assets/images/wpo-helper.png'; ?>" class="wpo-helper">
|
16 |
<h3><?php _e( 'Check out these premium extensions!', 'woocommerce-pdf-invoices-packing-slips' ); ?></h3>
|
17 |
<i>(<?php _e( 'click items to read more', 'woocommerce-pdf-invoices-packing-slips' ); ?>)</i>
|
@@ -125,7 +125,7 @@ jQuery(document).ready(function() {
|
|
125 |
</ul>
|
126 |
<?php
|
127 |
// link to hide message when one of the premium extensions is installed
|
128 |
-
if ( class_exists('WooCommerce_PDF_IPS_Pro') || class_exists('
|
129 |
printf('<a href="%s" style="display:inline-block; margin-top: 10px;">%s</a>', add_query_arg( 'wpo_wcpdf_hide_extensions_ad', 'true' ), __( 'Hide this message', 'woocommerce-pdf-invoices-packing-slips' ) );
|
130 |
}
|
131 |
?>
|
11 |
</script>
|
12 |
|
13 |
<div class="wcpdf-extensions-ad">
|
14 |
+
<?php $no_pro = !class_exists('WooCommerce_PDF_IPS_Pro') && !class_exists('WPO_WCPDF_Templates'); ?>
|
15 |
<img src="<?php echo WPO_WCPDF()->plugin_url() . '/assets/images/wpo-helper.png'; ?>" class="wpo-helper">
|
16 |
<h3><?php _e( 'Check out these premium extensions!', 'woocommerce-pdf-invoices-packing-slips' ); ?></h3>
|
17 |
<i>(<?php _e( 'click items to read more', 'woocommerce-pdf-invoices-packing-slips' ); ?>)</i>
|
125 |
</ul>
|
126 |
<?php
|
127 |
// link to hide message when one of the premium extensions is installed
|
128 |
+
if ( class_exists('WooCommerce_PDF_IPS_Pro') || class_exists('WPO_WCPDF_Templates') || class_exists('WooCommerce_PDF_IPS_Templates') || class_exists('WooCommerce_Ext_PrintOrders') || class_exists('WPO_WC_Smart_Reminder_Emails') ) {
|
129 |
printf('<a href="%s" style="display:inline-block; margin-top: 10px;">%s</a>', add_query_arg( 'wpo_wcpdf_hide_extensions_ad', 'true' ), __( 'Hide this message', 'woocommerce-pdf-invoices-packing-slips' ) );
|
130 |
}
|
131 |
?>
|
includes/views/wcpdf-settings-page.php
CHANGED
@@ -1,52 +1,52 @@
|
|
1 |
-
<?php defined( 'ABSPATH' ) or exit; ?>
|
2 |
-
<script type="text/javascript">
|
3 |
-
jQuery( function( $ ) {
|
4 |
-
$("#footer-thankyou").html("If you like <strong>WooCommerce PDF Invoices & Packing Slips</strong> please leave us a <a href='https://wordpress.org/support/view/plugin-reviews/woocommerce-pdf-invoices-packing-slips?rate=5#postform'>★★★★★</a> rating. A huge thank you in advance!");
|
5 |
-
});
|
6 |
-
</script>
|
7 |
-
<div class="wrap">
|
8 |
-
<div class="icon32" id="icon-options-general"><br /></div>
|
9 |
-
<h2><?php _e( 'WooCommerce PDF Invoices', 'woocommerce-pdf-invoices-packing-slips' ); ?></h2>
|
10 |
-
<h2 class="nav-tab-wrapper">
|
11 |
-
<?php
|
12 |
-
foreach ($settings_tabs as $tab_slug => $tab_title ) {
|
13 |
-
$tab_link = esc_url("?page=wpo_wcpdf_options_page&tab={$tab_slug}");
|
14 |
-
printf('<a href="%1$s" class="nav-tab nav-tab-%2$s %3$s">%4$s</a>', $tab_link, $tab_slug, (($active_tab == $tab_slug) ? 'nav-tab-active' : ''), $tab_title);
|
15 |
-
}
|
16 |
-
?>
|
17 |
-
</h2>
|
18 |
-
|
19 |
-
<?php
|
20 |
-
do_action( 'wpo_wcpdf_before_settings_page', $active_tab, $active_section );
|
21 |
-
|
22 |
-
// save or check option to hide extensions ad
|
23 |
-
if ( isset( $_GET['wpo_wcpdf_hide_extensions_ad'] ) ) {
|
24 |
-
update_option( 'wpo_wcpdf_hide_extensions_ad', true );
|
25 |
-
$hide_ad = true;
|
26 |
-
} else {
|
27 |
-
$hide_ad = get_option( 'wpo_wcpdf_hide_extensions_ad' );
|
28 |
-
}
|
29 |
-
|
30 |
-
if ( !$hide_ad && !( class_exists('WooCommerce_PDF_IPS_Pro') && class_exists('
|
31 |
-
include('wcpdf-extensions.php');
|
32 |
-
}
|
33 |
-
|
34 |
-
?>
|
35 |
-
<form method="post" action="options.php" id="wpo-wcpdf-settings" class="<?php echo "{$active_tab} {$active_section}"; ?>">
|
36 |
-
<?php
|
37 |
-
do_action( 'wpo_wcpdf_before_settings', $active_tab, $active_section );
|
38 |
-
if ( has_action( 'wpo_wcpdf_settings_output_'.$active_tab ) ) {
|
39 |
-
do_action( 'wpo_wcpdf_settings_output_'.$active_tab, $active_section );
|
40 |
-
} else {
|
41 |
-
// legacy settings
|
42 |
-
settings_fields( "wpo_wcpdf_{$active_tab}_settings" );
|
43 |
-
do_settings_sections( "wpo_wcpdf_{$active_tab}_settings" );
|
44 |
-
|
45 |
-
submit_button();
|
46 |
-
}
|
47 |
-
do_action( 'wpo_wcpdf_after_settings', $active_tab, $active_section );
|
48 |
-
?>
|
49 |
-
|
50 |
-
</form>
|
51 |
-
<?php do_action( 'wpo_wcpdf_after_settings_page', $active_tab, $active_section ); ?>
|
52 |
-
</div>
|
1 |
+
<?php defined( 'ABSPATH' ) or exit; ?>
|
2 |
+
<script type="text/javascript">
|
3 |
+
jQuery( function( $ ) {
|
4 |
+
$("#footer-thankyou").html("If you like <strong>WooCommerce PDF Invoices & Packing Slips</strong> please leave us a <a href='https://wordpress.org/support/view/plugin-reviews/woocommerce-pdf-invoices-packing-slips?rate=5#postform'>★★★★★</a> rating. A huge thank you in advance!");
|
5 |
+
});
|
6 |
+
</script>
|
7 |
+
<div class="wrap">
|
8 |
+
<div class="icon32" id="icon-options-general"><br /></div>
|
9 |
+
<h2><?php _e( 'WooCommerce PDF Invoices', 'woocommerce-pdf-invoices-packing-slips' ); ?></h2>
|
10 |
+
<h2 class="nav-tab-wrapper">
|
11 |
+
<?php
|
12 |
+
foreach ($settings_tabs as $tab_slug => $tab_title ) {
|
13 |
+
$tab_link = esc_url("?page=wpo_wcpdf_options_page&tab={$tab_slug}");
|
14 |
+
printf('<a href="%1$s" class="nav-tab nav-tab-%2$s %3$s">%4$s</a>', $tab_link, $tab_slug, (($active_tab == $tab_slug) ? 'nav-tab-active' : ''), $tab_title);
|
15 |
+
}
|
16 |
+
?>
|
17 |
+
</h2>
|
18 |
+
|
19 |
+
<?php
|
20 |
+
do_action( 'wpo_wcpdf_before_settings_page', $active_tab, $active_section );
|
21 |
+
|
22 |
+
// save or check option to hide extensions ad
|
23 |
+
if ( isset( $_GET['wpo_wcpdf_hide_extensions_ad'] ) ) {
|
24 |
+
update_option( 'wpo_wcpdf_hide_extensions_ad', true );
|
25 |
+
$hide_ad = true;
|
26 |
+
} else {
|
27 |
+
$hide_ad = get_option( 'wpo_wcpdf_hide_extensions_ad' );
|
28 |
+
}
|
29 |
+
|
30 |
+
if ( !$hide_ad && !( class_exists('WooCommerce_PDF_IPS_Pro') && class_exists('WooCommerce_PDF_IPS_Templates') && class_exists('WooCommerce_Ext_PrintOrders') ) ) {
|
31 |
+
include('wcpdf-extensions.php');
|
32 |
+
}
|
33 |
+
|
34 |
+
?>
|
35 |
+
<form method="post" action="options.php" id="wpo-wcpdf-settings" class="<?php echo "{$active_tab} {$active_section}"; ?>">
|
36 |
+
<?php
|
37 |
+
do_action( 'wpo_wcpdf_before_settings', $active_tab, $active_section );
|
38 |
+
if ( has_action( 'wpo_wcpdf_settings_output_'.$active_tab ) ) {
|
39 |
+
do_action( 'wpo_wcpdf_settings_output_'.$active_tab, $active_section );
|
40 |
+
} else {
|
41 |
+
// legacy settings
|
42 |
+
settings_fields( "wpo_wcpdf_{$active_tab}_settings" );
|
43 |
+
do_settings_sections( "wpo_wcpdf_{$active_tab}_settings" );
|
44 |
+
|
45 |
+
submit_button();
|
46 |
+
}
|
47 |
+
do_action( 'wpo_wcpdf_after_settings', $active_tab, $active_section );
|
48 |
+
?>
|
49 |
+
|
50 |
+
</form>
|
51 |
+
<?php do_action( 'wpo_wcpdf_after_settings_page', $active_tab, $active_section ); ?>
|
52 |
+
</div>
|
readme.txt
CHANGED
@@ -5,7 +5,7 @@ Tags: woocommerce, pdf, invoices, packing slips, print, delivery notes, invoice,
|
|
5 |
Requires at least: 3.5
|
6 |
Tested up to: 5.5
|
7 |
Requires PHP: 5.3
|
8 |
-
Stable tag: 2.
|
9 |
License: GPLv2 or later
|
10 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
11 |
|
@@ -102,6 +102,12 @@ There's a setting on the Status tab of the settings page that allows you to togg
|
|
102 |
|
103 |
== Changelog ==
|
104 |
|
|
|
|
|
|
|
|
|
|
|
|
|
105 |
= 2.6.1 =
|
106 |
* Fix: Load custom documents once rather than on every document request
|
107 |
* Tweak: execute wpo_wcpdf_init_document action in invoice too
|
5 |
Requires at least: 3.5
|
6 |
Tested up to: 5.5
|
7 |
Requires PHP: 5.3
|
8 |
+
Stable tag: 2.7.0
|
9 |
License: GPLv2 or later
|
10 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
11 |
|
102 |
|
103 |
== Changelog ==
|
104 |
|
105 |
+
= 2.7.0 =
|
106 |
+
* New: Add per-order notes to invoices (requires template update if you have a custom template)
|
107 |
+
* New: Show notice with instructions for protecting the invoice folder on NGINX setups
|
108 |
+
* Fix: Show correct "next number" on settings page for sites using MySQL 8+
|
109 |
+
* Tested up to WooCommerce 4.6
|
110 |
+
|
111 |
= 2.6.1 =
|
112 |
* Fix: Load custom documents once rather than on every document request
|
113 |
* Tweak: execute wpo_wcpdf_init_document action in invoice too
|
templates/Simple/invoice.php
CHANGED
@@ -113,6 +113,14 @@
|
|
113 |
<tfoot>
|
114 |
<tr class="no-borders">
|
115 |
<td class="no-borders">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
<div class="customer-notes">
|
117 |
<?php do_action( 'wpo_wcpdf_before_customer_notes', $this->type, $this->order ); ?>
|
118 |
<?php if ( $this->get_shipping_notes() ) : ?>
|
113 |
<tfoot>
|
114 |
<tr class="no-borders">
|
115 |
<td class="no-borders">
|
116 |
+
<div class="document-notes">
|
117 |
+
<?php do_action( 'wpo_wcpdf_before_document_notes', $this->type, $this->order ); ?>
|
118 |
+
<?php if ( $this->get_document_notes() ) : ?>
|
119 |
+
<h3><?php _e( 'Notes', 'woocommerce-pdf-invoices-packing-slips' ); ?></h3>
|
120 |
+
<?php $this->document_notes(); ?>
|
121 |
+
<?php endif; ?>
|
122 |
+
<?php do_action( 'wpo_wcpdf_after_document_notes', $this->type, $this->order ); ?>
|
123 |
+
</div>
|
124 |
<div class="customer-notes">
|
125 |
<?php do_action( 'wpo_wcpdf_before_customer_notes', $this->type, $this->order ); ?>
|
126 |
<?php if ( $this->get_shipping_notes() ) : ?>
|
templates/Simple/style.css
CHANGED
@@ -221,6 +221,7 @@ dd:after {
|
|
221 |
}
|
222 |
|
223 |
/* Notes & Totals */
|
|
|
224 |
.customer-notes {
|
225 |
margin-top: 5mm;
|
226 |
}
|
221 |
}
|
222 |
|
223 |
/* Notes & Totals */
|
224 |
+
.document-notes,
|
225 |
.customer-notes {
|
226 |
margin-top: 5mm;
|
227 |
}
|
woocommerce-pdf-invoices-packingslips.php
CHANGED
@@ -3,14 +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: 2.
|
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: woocommerce-pdf-invoices-packing-slips
|
12 |
* WC requires at least: 2.2.0
|
13 |
-
* WC tested up to: 4.
|
14 |
*/
|
15 |
|
16 |
if ( ! defined( 'ABSPATH' ) ) {
|
@@ -21,7 +21,7 @@ if ( !class_exists( 'WPO_WCPDF' ) ) :
|
|
21 |
|
22 |
class WPO_WCPDF {
|
23 |
|
24 |
-
public $version = '2.
|
25 |
public $plugin_basename;
|
26 |
public $legacy_mode;
|
27 |
|
@@ -52,6 +52,7 @@ class WPO_WCPDF {
|
|
52 |
add_filter( 'load_textdomain_mofile', array( $this, 'textdomain_fallback' ), 10, 2 );
|
53 |
add_action( 'plugins_loaded', array( $this, 'load_classes' ), 9 );
|
54 |
add_action( 'in_plugin_update_message-'.$this->plugin_basename, array( $this, 'in_plugin_update_message' ) );
|
|
|
55 |
}
|
56 |
|
57 |
/**
|
@@ -325,6 +326,35 @@ class WPO_WCPDF {
|
|
325 |
return wp_kses_post( $upgrade_notice );
|
326 |
}
|
327 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
328 |
/**
|
329 |
* Get the plugin url.
|
330 |
* @return string
|
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: 2.7.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: woocommerce-pdf-invoices-packing-slips
|
12 |
* WC requires at least: 2.2.0
|
13 |
+
* WC tested up to: 4.6.0
|
14 |
*/
|
15 |
|
16 |
if ( ! defined( 'ABSPATH' ) ) {
|
21 |
|
22 |
class WPO_WCPDF {
|
23 |
|
24 |
+
public $version = '2.7.0';
|
25 |
public $plugin_basename;
|
26 |
public $legacy_mode;
|
27 |
|
52 |
add_filter( 'load_textdomain_mofile', array( $this, 'textdomain_fallback' ), 10, 2 );
|
53 |
add_action( 'plugins_loaded', array( $this, 'load_classes' ), 9 );
|
54 |
add_action( 'in_plugin_update_message-'.$this->plugin_basename, array( $this, 'in_plugin_update_message' ) );
|
55 |
+
add_action( 'admin_notices', array( $this, 'nginx_detected' ) );
|
56 |
}
|
57 |
|
58 |
/**
|
326 |
return wp_kses_post( $upgrade_notice );
|
327 |
}
|
328 |
|
329 |
+
public function nginx_detected()
|
330 |
+
{
|
331 |
+
if ( empty( $this->main ) ) {
|
332 |
+
return;
|
333 |
+
}
|
334 |
+
$tmp_path = $this->main->get_tmp_path('attachments');
|
335 |
+
$server_software = isset( $_SERVER['SERVER_SOFTWARE'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) : false;
|
336 |
+
if ( stristr( $server_software, 'nginx' ) && ( current_user_can( 'manage_shop_settings' ) || current_user_can( 'manage_woocommerce' ) ) && ! get_option('wpo_wcpdf_hide_nginx_notice') ) {
|
337 |
+
ob_start();
|
338 |
+
?>
|
339 |
+
<div class="error">
|
340 |
+
<img src="<?php echo WPO_WCPDF()->plugin_url() . "/assets/images/nginx.svg"; ?>" style="margin-top:10px;">
|
341 |
+
<p><?php printf( __( 'The PDF files in %s are not currently protected due to your site running on <strong>NGINX</strong>.', 'woocommerce-pdf-invoices-packing-slips' ), '<strong>' . $tmp_path . '</strong>' ); ?></p>
|
342 |
+
<p><?php _e( 'To protect them, you must either use a filter to change the folder to a more secure location (outside of the site root folder) or add a Virtual Host location rule as explained in <a href="https://docs.wpovernight.com/woocommerce-pdf-invoices-packing-slips/protect-the-attachments-directory-on-nginx/" target="_blank">this guide</a>.', 'woocommerce-pdf-invoices-packing-slips' ); ?></p>
|
343 |
+
<p><?php _e( 'If you have already added the filter or the vhost rule, you may safely hide this message.', 'woocommerce-pdf-invoices-packing-slips' ); ?></p>
|
344 |
+
<p><a href="<?php echo esc_url( add_query_arg( 'wpo_wcpdf_hide_nginx_notice', 'true' ) ); ?>"><?php _e( 'Hide this message', 'woocommerce-pdf-invoices-packing-slips' ); ?></a></p>
|
345 |
+
</div>
|
346 |
+
<?php
|
347 |
+
echo ob_get_clean();
|
348 |
+
}
|
349 |
+
|
350 |
+
// save option to hide nginx notice
|
351 |
+
if ( isset( $_GET['wpo_wcpdf_hide_nginx_notice'] ) ) {
|
352 |
+
update_option( 'wpo_wcpdf_hide_nginx_notice', true );
|
353 |
+
wp_redirect( 'admin.php?page=wpo_wcpdf_options_page' );
|
354 |
+
exit;
|
355 |
+
}
|
356 |
+
}
|
357 |
+
|
358 |
/**
|
359 |
* Get the plugin url.
|
360 |
* @return string
|