prefix . 'wc_orders'; } /** * HPOS order addresses table name. * * @return string */ public static function addressesTable(): string { global $wpdb; return $wpdb->prefix . 'wc_order_addresses'; } /** * HPOS operational data table name. * * @return string */ public static function operationalDataTable(): string { global $wpdb; return $wpdb->prefix . 'wc_order_operational_data'; } /** * HPOS order meta table name. * * @return string */ public static function metaTable(): string { global $wpdb; return $wpdb->prefix . 'wc_orders_meta'; } /** * Order items table name (shared legacy table). * * @return string */ public static function itemsTable(): string { global $wpdb; return $wpdb->prefix . 'woocommerce_order_items'; } /** * Order item meta table name (shared legacy table). * * @return string */ public static function itemMetaTable(): string { global $wpdb; return $wpdb->prefix . 'woocommerce_order_itemmeta'; } /** * Every source table an order's data is spread across, keyed by the name * we use inside the archive payload. * * This is also the allowlist: no table name reaches a query unless it came * from here. Nothing user-supplied is ever interpolated into SQL. * * @return array */ public static function sourceTables(): array { return array( 'order' => self::ordersTable(), 'addresses' => self::addressesTable(), 'operational_data' => self::operationalDataTable(), 'meta' => self::metaTable(), 'items' => self::itemsTable(), 'item_meta' => self::itemMetaTable(), ); } /** * Storage engine of the orders table. Archiving runs each order inside a * transaction, which silently does nothing on MyISAM — so we check. */ public static function supportsTransactions(): bool { global $wpdb; $table = self::ordersTable(); // phpcs:ignore WordPress.DB.DirectDatabaseQuery $engine = $wpdb->get_var( $wpdb->prepare( 'SELECT ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s', $table ) ); return is_string( $engine ) && strtoupper( $engine ) === 'INNODB'; } }