*/ private static array $touched = []; /** * Whether the shutdown flush is hooked already. * * @var bool */ private static bool $hooked = false; /** * An order or refund was saved. * * @param mixed $order The saved object. * * @internal Hooked callback. */ public function saved( $order ): void { if ( $order instanceof \WC_Order_Refund ) { $this->touch( (int) $order->get_parent_id() ); return; } if ( $order instanceof WC_Order ) { $this->touch( $order->get_id() ); } } /** * An order was trashed, deleted or restored; shutdown looks at what is left. * * @param mixed $orderId Order id. * * @internal Hooked callback. */ public function changed( $orderId ): void { $this->touch( (int) $orderId ); } /** * Record every touched order and rebuild the customers they belong to. * * @internal Hooked to `shutdown`. */ public function flush(): void { $ids = array_keys( self::$touched ); self::$touched = []; $customers = []; foreach ( $ids as $id ) { $order = function_exists( 'wc_get_order' ) ? wc_get_order( $id ) : false; if ( $order instanceof WC_Order && 'trash' !== $order->get_status() ) { foreach ( Stats::record( $order ) as $hash ) { $customers[ $hash ] = true; } } else { $owner = Stats::forget( $id ); if ( null !== $owner ) { $customers[ $owner ] = true; } } } foreach ( array_keys( $customers ) as $hash ) { Stats::rebuild( $hash ); } } /** * Note an order, and hook the flush the first time. * * @param int $orderId Order id. */ private function touch( int $orderId ): void { if ( $orderId < 1 ) { return; } self::$touched[ $orderId ] = true; if ( ! self::$hooked ) { self::$hooked = true; add_action( 'shutdown', fn() => $this->flush(), 5 ); } } }