Created
December 8, 2024 08:45
-
-
Save geekontheroad/57e524d5f2f6ddf07b2501a15d2a5f15 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* This class is to import orders/entries made through GF Product Addon into GS Product Configurator. | |
* Based on the GWiz_Batcher class included with the GS Product Configurator so this class will only work if the GS Product Configurator is also installed. | |
* The tool will log messages to the GS Product Configurator log file so ensure to enable logging before running this tool. | |
* | |
* INSTRUCTIONS | |
* - Copy the below class to your functions.php or code snippet plugin. | |
* - Navigate to the GS Product Configurator settings under the forms settings menu and you should see the new panel called 'WCGFPA Orders sync' | |
* - Press Start Batch to start the migration process. | |
* - Optional: Remove this class after usage. | |
* | |
* @link https://geekontheroad.com | |
* @link https://gravitywiz.com/documentation/gravity-shop-product-configurator/ | |
* @author Johan d'Hollander | |
* @version 1.0 | |
*/ | |
if ( class_exists( '\GS_Product_Configurator\GWiz_Batcher' ) && ! class_exists( 'Gotrgs_Orders_Importer_WCGFPA' ) ) { | |
class Gotrgs_Orders_Importer_WCGFPA { | |
/** | |
* @var GWiz_Batcher Batcher instance. | |
*/ | |
public $batcher = null; | |
public function __construct() { | |
// 20 priority since we'll be after 15 at this point | |
add_action( 'init', array( $this, 'register_batcher' ), 20 ); | |
// Add a new panel to the plugin settings if enabled. | |
add_filter( 'gspc_plugin_settings_fields', array( $this, 'add_plugin_settings_panel' ) ); | |
} | |
/** | |
* Adds a new panel to the GSPC plugin settings if enabled. | |
* | |
* @param mixed[] $plugin_settings | |
* | |
* @return mixed[] | |
*/ | |
public function add_plugin_settings_panel( $plugin_settings ) { | |
/** @phpstan-ignore-next-line */ | |
if ( ! $this->batcher ) { | |
$this->register_batcher(); | |
} | |
$plugin_settings['wcgfpa_orders_sync'] = [ | |
'title' => __( 'WCGFPA Orders sync', 'gs-product-configurator' ), | |
'description' => __( 'Sync order and entry data to GS Product configurator for orders made through WCGFPA.', 'gs-product-configurator' ), | |
'fields' => array( | |
'wcgfpa_orders_sync' => array( | |
'type' => 'html', | |
'html' => $this->batcher->render(), | |
), | |
), | |
]; | |
return $plugin_settings; | |
} | |
/** | |
* Adds a GWiz Batcher to migrate order and entry data from WCGFPA to GSPC. | |
* | |
* This batcher is meant to be idempotent where if you re-run it, you'll get the same result given | |
* the same WCGFPA data. | |
* | |
* @return void | |
*/ | |
function register_batcher() { | |
$this->batcher = new \GS_Product_Configurator\GWiz_Batcher( array( | |
'title' => __( 'WCGFPA to GSPC Order and Entry Migrator', 'gs-product-configurator' ), | |
'id' => 'wcgfpa-to-gspc-orders-migrator', | |
'create_admin_page' => false, | |
'size' => 20, | |
'get_items' => [ $this, 'get_batcher_items' ], | |
'process_item' => [ $this, 'batcher_process_item' ], | |
'on_finish' => function( $count, $total ) { | |
// Do nothing. | |
}, | |
) ); | |
} | |
/** | |
* Gets the items for the batcher. | |
* | |
* @param int $size | |
* @param int $offset | |
* @param int|null $form_id | |
* | |
* @return array{ | |
* items: \WC_Product[], | |
* total: int, | |
* } | |
*/ | |
public function get_batcher_items( $size, $offset, $form_id = null ) { | |
// Set up the query arguments for fetching orders | |
$args = array( | |
'limit' => $size, | |
'offset' => $offset, | |
'return' => 'objects', | |
); | |
// Get the orders using wc_get_orders | |
$orders = wc_get_orders( $args ); | |
gs_product_configurator()->log_debug( __METHOD__ . ' total orders count ' . $total_orders ); | |
// Return the array with items (orders) and total count | |
return array( | |
'items' => $orders, // This contains the array of WC_Order objects matching our arguments. | |
'total' => $this->get_total_order_count(), | |
); | |
} | |
/** | |
* Processes an order. | |
* We need to update the item data as well as the GF entry data. | |
* | |
* @param \WC_Product $product | |
* | |
* @return void | |
*/ | |
public function batcher_process_item( $order ) { | |
if ( ! is_a( $order, 'WC_Order' ) ) { | |
return; | |
} | |
if ( count( $order->get_items() ) > 0 ) { | |
foreach ( $order->get_items() as $item_id => $item ) { | |
$gravity_forms_history = wc_get_order_item_meta($item_id, '_gravity_forms_history', true); | |
if (!empty($gravity_forms_history)) { | |
// Deserialize the serialized data | |
$history_data = maybe_unserialize($gravity_forms_history); | |
// Check if the linked entry ID and form ID exist in the data | |
if (isset($history_data['_gravity_form_linked_entry_id']) && isset($history_data['_gravity_form_lead']['form_id'])) { | |
$entry_id = $history_data['_gravity_form_linked_entry_id']; | |
$form_id = $history_data['_gravity_form_lead']['form_id']; | |
$product_id = $item->get_product_id(); | |
$this->update_item_meta( $item_id, 'gspc_gf_entry_ids', array( $entry_id ) ); | |
$this->update_item_meta( $item_id, 'gspc_gf_form_id', $form_id ); | |
$this->update_entry_data( $entry_id, $order->get_id(), $product_id ); | |
} else { | |
$this->log_processing_error( $order->get_id(), 'No linked entry ID or form ID found in order item' ); | |
continue; | |
} | |
} else { | |
$this->log_processing_error( $order->get_id(), 'No Gravity Forms history found in order item' ); | |
continue; | |
} | |
} | |
} else { | |
$this->log_processing_error( $order->get_id(), 'No items found in order' ); | |
} | |
} | |
/** | |
* Update the item meta data. | |
* | |
* @param int $item_id | |
* @param string $meta_key | |
* @param mixed $meta_value | |
* | |
* @return void | |
*/ | |
private function update_item_meta( $item_id, $meta_key, $meta_value ) { | |
wc_update_order_item_meta( $item_id, $meta_key, $meta_value ); | |
} | |
/** | |
* Update the entry data. | |
* | |
* @param int $entry_id | |
* @param int $order_id | |
* @param int $product_id | |
* | |
* @return void | |
*/ | |
private function update_entry_data( $entry_id, $order_id, $product_id ) { | |
$entry = GFAPI::get_entry( $entry_id ); | |
if ( is_wp_error( $entry ) ) { | |
$this->log_processing_error( $order_id, sprintf( 'Failed to get entry %s: %s', $entry_id, $entry->get_error_message() ) ); | |
return; | |
} | |
$entry['transaction_id'] = $order_id; | |
$entry['gspc_wc_order_item_id'] = $order_id; | |
$entry['gspc_wc_product_id'] = $product_id; | |
$updated = GFAPI::update_entry( $entry ); | |
if ( is_wp_error( $updated ) ) { | |
$this->log_processing_error( $order_id, sprintf( 'Failed to update entry %s: %s', $entry_id, $updated->get_error_message() ) ); | |
} | |
} | |
/** | |
* Log processing error. | |
* | |
* @param int $order_id | |
* @param string $error_message | |
* | |
* @return void | |
*/ | |
private function log_processing_error( $order_id, $error_message ) { | |
gs_product_configurator()->log_debug( __METHOD__ . '():' . sprintf( 'Failed to process order %s: %s', $order_id, $error_message ) ); | |
} | |
/** | |
* Get the total order count. | |
* | |
* @return int | |
*/ | |
private function get_total_order_count() { | |
$order_statuses = wc_get_order_statuses(); | |
$count = 0; | |
foreach( array_keys( $order_statuses ) as $status_key ) { | |
$count += wc_orders_count( str_replace( 'wc-', '', $status_key ) ); | |
} | |
return $count; | |
} | |
} | |
new Gotrgs_Orders_Importer_WCGFPA(); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment