Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: renumbering documents not working #705

Merged
merged 15 commits into from
Feb 9, 2024
90 changes: 90 additions & 0 deletions includes/documents/abstract-wcpdf-order-document.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use WPO\WC\UBL\Builders\SabreBuilder;
use WPO\WC\UBL\Documents\UblDocument;
use WPO\WC\PDF_Invoices\Updraft_Semaphore_3_0 as Semaphore;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
Expand Down Expand Up @@ -84,6 +85,36 @@ abstract class Order_Document {
* @var array
*/
public $output_formats = array();

/**
* Semaphore lock name.
* @var string
*/
private $lock_name;

/**
* Semaphore lock context.
* @var array
*/
private $lock_context = array( 'source' => 'wpo-wcpdf-document-semaphore' );

/**
* Semaphore lock time.
* @var int
*/
private $lock_time;

/**
* Semaphore lock retries.
* @var int
*/
private $lock_retries;

/**
* Semaphore lock loggers.
* @var array
*/
private $lock_loggers;

/**
* Linked documents, used for data retrieval
Expand All @@ -103,6 +134,12 @@ abstract class Order_Document {
* @param int|object|WC_Order $order Order to init.
*/
public function __construct( $order = 0 ) {
// semaphore
$this->lock_name = "wpo_wcpdf_{$this->slug}_semaphore_lock";
alexmigf marked this conversation as resolved.
Show resolved Hide resolved
$this->lock_time = apply_filters( 'wpo_wcpdf_document_semaphore_lock_time', 60 );
alexmigf marked this conversation as resolved.
Show resolved Hide resolved
$this->lock_retries = apply_filters( 'wpo_wcpdf_document_semaphore_lock_retries', 0 );
$this->lock_loggers = apply_filters( 'wpo_wcpdf_document_semaphore_lock_loggers', isset( WPO_WCPDF()->settings->debug_settings['semaphore_logs'] ) ? array( wc_get_logger() ) : array() );

if ( is_numeric( $order ) && $order > 0 ) {
$this->order_id = $order;
$this->order = wc_get_order( $this->order_id );
Expand Down Expand Up @@ -224,6 +261,59 @@ public function save_settings( $latest = false ) {
}
}
}

public function init_number( $force_new_number = false ) {
$lock = new Semaphore( $this->lock_name, $this->lock_time, $this->lock_loggers, $this->lock_context );
$document_number = $this->exists() ? $this->get_data( 'number' ) : null;
$document_number = ! empty( $document_number ) && $force_new_number ? null : $document_number;

if ( $lock->lock( $this->lock_retries ) && empty( $document_number ) ) {

$lock->log( "Lock acquired for the {$this->slug} number init.", 'info' );

try {
// If a third-party plugin claims to generate document numbers, trigger this instead
if ( apply_filters( "woocommerce_{$this->slug}_number_by_plugin", false ) || apply_filters( "wpo_wcpdf_external_{$this->slug}_number_enabled", false, $this ) ) {
$document_number = apply_filters( "woocommerce_generate_{$this->slug}_number", $document_number, $this->order ); // legacy (backwards compatibility)
$document_number = apply_filters( "woocommerce_{$this->slug}_number", $document_number, $this->order->get_id() ); // legacy (backwards compatibility)
$document_number = apply_filters( "wpo_wcpdf_external_{$this->slug}_number", $document_number, $this );
} elseif ( isset( $this->settings['display_number'] ) && 'order_number' === $this->settings['display_number'] && ! empty( $this->order ) ) {
$document_number = $this->order->get_order_number();
alexmigf marked this conversation as resolved.
Show resolved Hide resolved
}

if ( ! empty( $document_number ) ) { // overridden by plugin or set to order number
if ( ! is_numeric( $document_number ) && ! ( $document_number instanceof Document_Number ) ) {
// document number is not numeric, treat as formatted
// try to extract meaningful number data
$formatted_number = $document_number;
$number = (int) preg_replace( '/\D/', '', $document_number );
$document_number = compact( 'number', 'formatted_number' );
}
} else {
$number_store = $this->get_sequential_number_store();
$document_number = $number_store->increment( intval( $this->order_id ), $this->get_date()->date_i18n( 'Y-m-d H:i:s' ) );
}

if ( ! is_null( $document_number ) ) {
$this->set_number( $document_number );
}

} catch ( \Exception $e ) {
$lock->log( $e, 'critical' );
} catch ( \Error $e ) {
$lock->log( $e, 'critical' );
}

if ( $lock->release() ) {
$lock->log( "Lock released for the {$this->slug} number init.", 'info' );
}

} else {
$lock->log( "Couldn't get the lock for the {$this->slug} number init.", 'critical' );
}

return $document_number;
}

public function maybe_use_latest_settings() {
return ! $this->use_historical_settings();
Expand Down
61 changes: 0 additions & 61 deletions includes/documents/class-wcpdf-invoice.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
<?php
namespace WPO\WC\PDF_Invoices\Documents;

use WPO\WC\PDF_Invoices\Updraft_Semaphore_3_0 as Semaphore;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
Expand Down Expand Up @@ -35,13 +33,6 @@ public function __construct( $order = 0 ) {
$this->type = 'invoice';
$this->title = __( 'Invoice', 'woocommerce-pdf-invoices-packing-slips' );
$this->icon = WPO_WCPDF()->plugin_url() . "/assets/images/invoice.svg";

// semaphore
$this->lock_name = "wpo_wcpdf_{$this->slug}_semaphore_lock";
$this->lock_context = array( 'source' => "wpo-wcpdf-semaphore" );
$this->lock_time = apply_filters( "wpo_wcpdf_{$this->type}_semaphore_lock_time", 60 );
$this->lock_retries = apply_filters( "wpo_wcpdf_{$this->type}_semaphore_lock_retries", 0 );
$this->lock_loggers = apply_filters( "wpo_wcpdf_{$this->type}_semaphore_lock_loggers", isset( WPO_WCPDF()->settings->debug_settings['semaphore_logs'] ) ? array( wc_get_logger() ) : array() );

// call parent constructor
parent::__construct( $order );
Expand Down Expand Up @@ -91,58 +82,6 @@ public function exists() {
return ! empty( $this->data['number'] );
}

public function init_number() {
$lock = new Semaphore( $this->lock_name, $this->lock_time, $this->lock_loggers, $this->lock_context );
$invoice_number = $this->exists() ? $this->data['number'] : null;

if ( $lock->lock( $this->lock_retries ) && empty( $invoice_number ) ) {

$lock->log( 'Lock acquired for the invoice number init.', 'info' );

try {
// If a third-party plugin claims to generate invoice numbers, trigger this instead
if ( apply_filters( 'woocommerce_invoice_number_by_plugin', false ) || apply_filters( 'wpo_wcpdf_external_invoice_number_enabled', false, $this ) ) {
$invoice_number = apply_filters( 'woocommerce_generate_invoice_number', $invoice_number, $this->order ); // legacy (backwards compatibility)
$invoice_number = apply_filters( 'woocommerce_invoice_number', $invoice_number, $this->order->get_id() ); // legacy (backwards compatibility)
$invoice_number = apply_filters( 'wpo_wcpdf_external_invoice_number', $invoice_number, $this );
} elseif ( isset( $this->settings['display_number'] ) && $this->settings['display_number'] == 'order_number' && ! empty( $this->order ) ) {
$invoice_number = $this->order->get_order_number();
}

if ( ! empty( $invoice_number ) ) { // overridden by plugin or set to order number
if ( ! is_numeric( $invoice_number ) && ! ( $invoice_number instanceof Document_Number ) ) {
// invoice number is not numeric, treat as formatted
// try to extract meaningful number data
$formatted_number = $invoice_number;
$number = (int) preg_replace( '/\D/', '', $invoice_number );
$invoice_number = compact( 'number', 'formatted_number' );
}
} else {
$number_store = $this->get_sequential_number_store();
$invoice_number = $number_store->increment( intval( $this->order_id ), $this->get_date()->date_i18n( 'Y-m-d H:i:s' ) );
}

if ( ! is_null( $invoice_number ) ) {
$this->set_number( $invoice_number );
}

} catch ( \Exception $e ) {
$lock->log( $e, 'critical' );
} catch ( \Error $e ) {
$lock->log( $e, 'critical' );
}

if ( $lock->release() ) {
$lock->log( 'Lock released for the invoice number init.', 'info' );
}

} else {
$lock->log( 'Couldn\'t get the lock for the invoice number init.', 'critical' );
}

return $invoice_number;
}

public function get_filename( $context = 'download', $args = array() ) {
$order_count = isset($args['order_ids']) ? count($args['order_ids']) : 1;

Expand Down
39 changes: 27 additions & 12 deletions includes/settings/class-wcpdf-settings-debug.php
Original file line number Diff line number Diff line change
Expand Up @@ -485,10 +485,10 @@ public function ajax_process_danger_zone_tools() {
$to_date = date_i18n( 'Y-m-d', strtotime( $request['date_to'] ) );
$document_type = esc_attr( $request['document_type'] );
$document_types = ! empty( $document_type ) && ( 'all' !== $document_type ) ? array( $document_type ) : array();
$document_title = ! empty( $document_type ) && ( 'all' !== $document_type ) ? ' ' . ucwords( str_replace( '-', ' ', $document_type ) ) . ' ' : ' ';
$page_count = absint( $request['page_count'] );
$document_count = absint( $request['document_count'] );
$delete_or_renumber = esc_attr( $request['delete_or_renumber'] );
$document_title = ! empty( $document_type ) && ( 'all' !== $document_type ) ? ucwords( str_replace( '-', ' ', $document_type ) ) . ' ' : ' ';
$page_count = isset( $request['page_count'] ) ? absint( $request['page_count'] ) : 1;
$document_count = isset( $request['document_count'] ) ? absint( $request['document_count'] ) : 0;
$delete_or_renumber = isset( $request['delete_or_renumber'] ) ? esc_attr( $request['delete_or_renumber'] ) : false;
$message = ( 'delete' === $delete_or_renumber ) ? $document_title . __( 'documents deleted.', 'woocommerce-pdf-invoices-packing-slips' ) : $document_title . __( 'documents renumbered.', 'woocommerce-pdf-invoices-packing-slips' );
$finished = false;

Expand All @@ -506,7 +506,7 @@ public function ajax_process_danger_zone_tools() {
$results = wc_get_orders( $args );
$order_ids = $results->orders;

if ( ! empty( $order_ids ) && ! empty( $document_type ) ) {
if ( ! empty( $order_ids ) && ! empty( $document_type ) && $delete_or_renumber ) {
foreach ( $order_ids as $order_id ) {
$order = wc_get_order( $order_id );

Expand Down Expand Up @@ -552,11 +552,28 @@ private function renumber_or_delete_document( $document, $delete_or_renumber ) {
if ( $document && $document->exists() ) {
switch ( $delete_or_renumber ) {
case 'renumber':
if ( is_callable( array( $document, 'init_number' ) ) ) {
$document->init_number();
$return = true;
} elseif ( 'packing-slip' === $document->get_type() && is_callable( array( WPO_WCPDF_Pro()->functions, 'init_packing_slip_number' ) ) ) {
WPO_WCPDF_Pro()->functions->init_packing_slip_number( $document );
// pro and third party documents
if ( 'invoice' !== $document->get_type() ) {
alexmigf marked this conversation as resolved.
Show resolved Hide resolved
// legacy
if ( function_exists( 'WPO_WCPDF_Pro' ) && version_compare( WPO_WCPDF_Pro()->version, '2.15.7', '<' ) ) {
// packing slip
if ( 'packing-slip' === $document->get_type() && is_callable( array( WPO_WCPDF_Pro()->functions, 'init_packing_slip_number' ) ) ) {
WPO_WCPDF_Pro()->functions->init_packing_slip_number( $document );
$return = true;
// other documents
} elseif ( is_callable( array( $document, 'init_number' ) ) ) {
$document->init_number();
$return = true;
}
// current
alexmigf marked this conversation as resolved.
Show resolved Hide resolved
} elseif ( is_callable( array( $document, 'init_number' ) ) ) {
$document->init_number( true );
$return = true;
}

// invoice from free plugin
} elseif ( is_callable( array( $document, 'init_number' ) ) ) {
$document->init_number( true );
$return = true;
}

Expand All @@ -570,8 +587,6 @@ private function renumber_or_delete_document( $document, $delete_or_renumber ) {
$return = true;
}
break;
default:
break;
}
}

Expand Down
Loading