@@ -17,6 +17,27 @@ class Order extends Generator {
1717 */
1818 const SECOND_REFUND_PROBABILITY = 25 ;
1919
20+ /**
21+ * Cached product IDs for batch operations.
22+ *
23+ * @var array|null
24+ */
25+ protected static $ batch_product_ids = null ;
26+
27+ /**
28+ * Cached coupon IDs for batch operations.
29+ *
30+ * @var array|null
31+ */
32+ protected static $ batch_coupon_ids = null ;
33+
34+ /**
35+ * Cached customer IDs for batch operations.
36+ *
37+ * @var array|null
38+ */
39+ protected static $ batch_customer_ids = null ;
40+
2041 /**
2142 * Return a new order.
2243 *
@@ -202,13 +223,19 @@ public static function batch( $amount, array $args = array() ) {
202223 return $ amount ;
203224 }
204225
226+ // Initialize batch cache to avoid repeated queries
227+ self ::init_batch_cache ( $ args );
228+
205229 $ order_ids = array ();
206230
207231 for ( $ i = 1 ; $ i <= $ amount ; $ i ++ ) {
208232 $ order = self ::generate ( true , $ args );
209233 $ order_ids [] = $ order ->get_id ();
210234 }
211235
236+ // Clear batch cache after generation
237+ self ::clear_batch_cache ();
238+
212239 return $ order_ids ;
213240 }
214241
@@ -224,9 +251,15 @@ public static function get_customer() {
224251 $ existing = (bool ) wp_rand ( 0 , 1 );
225252
226253 if ( $ existing ) {
227- $ total_users = (int ) $ wpdb ->get_var ( "SELECT COUNT(*) FROM {$ wpdb ->users }" );
228- $ offset = wp_rand ( 0 , $ total_users );
229- $ user_id = (int ) $ wpdb ->get_var ( "SELECT ID FROM {$ wpdb ->users } ORDER BY rand() LIMIT $ offset, 1 " ); // phpcs:ignore
254+ // Use cached customer IDs if available (batch mode)
255+ if ( null !== self ::$ batch_customer_ids && ! empty ( self ::$ batch_customer_ids ) ) {
256+ $ user_id = self ::$ batch_customer_ids [ array_rand ( self ::$ batch_customer_ids ) ];
257+ } else {
258+ // Fallback to direct query for single order generation
259+ $ total_users = (int ) $ wpdb ->get_var ( "SELECT COUNT(*) FROM {$ wpdb ->users }" );
260+ $ offset = wp_rand ( 0 , $ total_users );
261+ $ user_id = (int ) $ wpdb ->get_var ( "SELECT ID FROM {$ wpdb ->users } ORDER BY rand() LIMIT $ offset, 1 " ); // phpcs:ignore
262+ }
230263 return new \WC_Customer ( $ user_id );
231264 }
232265
@@ -298,27 +331,51 @@ protected static function get_random_products( int $min_amount = 1, int $max_amo
298331
299332 $ products = array ();
300333
301- $ num_existing_products = (int ) $ wpdb ->get_var (
302- "SELECT COUNT( DISTINCT ID )
303- FROM {$ wpdb ->posts }
304- WHERE 1=1
305- AND post_type='product'
306- AND post_status='publish' "
307- );
334+ // Use cached product IDs if available (batch mode)
335+ if ( null !== self ::$ batch_product_ids && ! empty ( self ::$ batch_product_ids ) ) {
336+ $ num_existing_products = count ( self ::$ batch_product_ids );
337+ $ num_products_to_get = wp_rand ( $ min_amount , $ max_amount );
308338
309- $ num_products_to_get = wp_rand ( $ min_amount , $ max_amount );
339+ if ( $ num_products_to_get > $ num_existing_products ) {
340+ $ num_products_to_get = $ num_existing_products ;
341+ }
310342
311- if ( $ num_products_to_get > $ num_existing_products ) {
312- $ num_products_to_get = $ num_existing_products ;
313- }
343+ // Get random product IDs from cache
344+ $ random_keys = array_rand ( self ::$ batch_product_ids , $ num_products_to_get );
345+ if ( ! is_array ( $ random_keys ) ) {
346+ $ random_keys = array ( $ random_keys );
347+ }
348+
349+ $ product_ids = array ();
350+ foreach ( $ random_keys as $ key ) {
351+ $ product_ids [] = self ::$ batch_product_ids [ $ key ];
352+ }
353+ } else {
354+ // Fallback to direct query for single order generation
355+ $ num_existing_products = (int ) $ wpdb ->get_var (
356+ "SELECT COUNT( DISTINCT ID )
357+ FROM {$ wpdb ->posts }
358+ WHERE 1=1
359+ AND post_type='product'
360+ AND post_status='publish' "
361+ );
314362
315- $ query = new \WC_Product_Query ( array (
316- 'limit ' => $ num_products_to_get ,
317- 'return ' => 'ids ' ,
318- 'orderby ' => 'rand ' ,
319- ) );
363+ $ num_products_to_get = wp_rand ( $ min_amount , $ max_amount );
320364
321- foreach ( $ query ->get_products () as $ product_id ) {
365+ if ( $ num_products_to_get > $ num_existing_products ) {
366+ $ num_products_to_get = $ num_existing_products ;
367+ }
368+
369+ $ query = new \WC_Product_Query ( array (
370+ 'limit ' => $ num_products_to_get ,
371+ 'return ' => 'ids ' ,
372+ 'orderby ' => 'rand ' ,
373+ ) );
374+
375+ $ product_ids = $ query ->get_products ();
376+ }
377+
378+ foreach ( $ product_ids as $ product_id ) {
322379 $ product = wc_get_product ( $ product_id );
323380
324381 if ( $ product ->is_type ( 'variable ' ) ) {
@@ -343,8 +400,8 @@ protected static function get_random_products( int $min_amount = 1, int $max_amo
343400 * @return \WC_Coupon|false Coupon object or false if none available.
344401 */
345402 protected static function get_or_create_coupon () {
346- // Try to get a random existing coupon
347- $ coupon = Coupon::get_random ();
403+ // Try to get a random existing coupon (pass cached IDs if available)
404+ $ coupon = Coupon::get_random ( self :: $ batch_coupon_ids );
348405
349406 // If no coupons exist, create 6 (3 fixed, 3 percentage)
350407 if ( false === $ coupon ) {
@@ -359,8 +416,13 @@ protected static function get_or_create_coupon() {
359416 return false ;
360417 }
361418
419+ // Update batch cache with newly created coupon IDs
420+ if ( null !== self ::$ batch_coupon_ids ) {
421+ self ::$ batch_coupon_ids = array_merge ( self ::$ batch_coupon_ids , $ fixed_result , $ percent_result );
422+ }
423+
362424 // Now get a random coupon from the ones we just created
363- $ coupon = Coupon::get_random ();
425+ $ coupon = Coupon::get_random ( self :: $ batch_coupon_ids );
364426 }
365427
366428 return $ coupon ;
@@ -721,4 +783,46 @@ protected static function create_refund( $order, $force_partial = false, $previo
721783
722784 return $ refund ;
723785 }
786+
787+ /**
788+ * Initialize batch cache by pre-loading IDs for products, coupons, and customers.
789+ * This significantly improves performance when generating multiple orders by avoiding
790+ * repeated database queries.
791+ *
792+ * @param array $args Arguments passed to batch generation (used to determine what to cache).
793+ * @return void
794+ */
795+ protected static function init_batch_cache ( $ args ) {
796+ global $ wpdb ;
797+
798+ // Load all product IDs once
799+ self ::$ batch_product_ids = $ wpdb ->get_col (
800+ "SELECT ID FROM {$ wpdb ->posts }
801+ WHERE post_type='product'
802+ AND post_status='publish' "
803+ );
804+
805+ // Load coupon IDs if coupon ratio is set
806+ if ( isset ( $ args ['coupon-ratio ' ] ) || isset ( $ args ['coupons ' ] ) ) {
807+ self ::$ batch_coupon_ids = $ wpdb ->get_col (
808+ "SELECT ID FROM {$ wpdb ->posts }
809+ WHERE post_type='shop_coupon'
810+ AND post_status='publish' "
811+ );
812+ }
813+
814+ // Load customer IDs
815+ self ::$ batch_customer_ids = $ wpdb ->get_col ( "SELECT ID FROM {$ wpdb ->users }" );
816+ }
817+
818+ /**
819+ * Clear batch cache after batch generation is complete.
820+ *
821+ * @return void
822+ */
823+ protected static function clear_batch_cache () {
824+ self ::$ batch_product_ids = null ;
825+ self ::$ batch_coupon_ids = null ;
826+ self ::$ batch_customer_ids = null ;
827+ }
724828}
0 commit comments