Commit e6299bc9220 for woocommerce
commit e6299bc9220ff2a53d63fdd6dd09a5863b971c33
Author: Jorge A. Torres <jorge.torres@automattic.com>
Date: Fri Mar 27 16:24:21 2026 +0000
Add periodic cleanup for order debug logs (#63756)
diff --git a/plugins/woocommerce/changelog/62143-cleanup-orphaned-order-debug-logs b/plugins/woocommerce/changelog/62143-cleanup-orphaned-order-debug-logs
new file mode 100644
index 00000000000..37ad8dcc01d
--- /dev/null
+++ b/plugins/woocommerce/changelog/62143-cleanup-orphaned-order-debug-logs
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Add periodic cleanup for place-order debug log files and dangling order meta that the existing batch processor doesn't cover.
diff --git a/plugins/woocommerce/includes/wc-core-functions.php b/plugins/woocommerce/includes/wc-core-functions.php
index 5ee994e06f8..9d732973e23 100644
--- a/plugins/woocommerce/includes/wc-core-functions.php
+++ b/plugins/woocommerce/includes/wc-core-functions.php
@@ -11,6 +11,7 @@
use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Utilities\NumberUtil;
use Automattic\WooCommerce\Blocks\Utils\CartCheckoutUtils;
+use Automattic\WooCommerce\Internal\Logging\OrderLogsCleanupHelper;
if ( ! defined( 'ABSPATH' ) ) {
exit;
@@ -2025,6 +2026,8 @@ function wc_cleanup_logs() {
if ( is_callable( array( $logger, 'clear_expired_logs' ) ) ) {
$logger->clear_expired_logs();
}
+
+ wc_get_container()->get( OrderLogsCleanupHelper::class )->cleanup();
}
add_action( 'woocommerce_cleanup_logs', 'wc_cleanup_logs' );
diff --git a/plugins/woocommerce/src/Internal/Logging/OrderLogsCleanupHelper.php b/plugins/woocommerce/src/Internal/Logging/OrderLogsCleanupHelper.php
new file mode 100644
index 00000000000..c8cebd525fd
--- /dev/null
+++ b/plugins/woocommerce/src/Internal/Logging/OrderLogsCleanupHelper.php
@@ -0,0 +1,248 @@
+<?php
+
+declare( strict_types=1 );
+
+namespace Automattic\WooCommerce\Internal\Logging;
+
+use Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController;
+use Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer;
+use WC_Logger;
+
+/**
+ * Handles cleanup of place-order debug log files and associated order meta.
+ *
+ * @since 10.7.0
+ */
+class OrderLogsCleanupHelper {
+
+ /**
+ * Maximum number of log files to delete per run.
+ */
+ public const MAX_FILES_PER_RUN = 100;
+
+ /**
+ * Maximum number of orders to clean up per run.
+ */
+ public const MAX_ORDERS_PER_RUN = 100;
+
+ /**
+ * True if HPOS is enabled.
+ *
+ * @var bool
+ */
+ private bool $hpos_in_use = false;
+
+ /**
+ * True if HPOS is disabled and the orders data store in use is the old CPT one.
+ *
+ * @var bool
+ */
+ private bool $cpt_in_use = false;
+
+ /**
+ * The instance of DataSynchronizer to use.
+ *
+ * @var DataSynchronizer
+ */
+ private DataSynchronizer $data_synchronizer;
+
+ /**
+ * Initialize the instance.
+ * This is invoked by the dependency injection container.
+ *
+ * @internal
+ *
+ * @param CustomOrdersTableController $hpos_controller The instance of CustomOrdersTableController to use.
+ * @param DataSynchronizer $data_synchronizer The instance of DataSynchronizer to use.
+ *
+ * @return void
+ */
+ final public function init( CustomOrdersTableController $hpos_controller, DataSynchronizer $data_synchronizer ): void {
+ $this->hpos_in_use = $hpos_controller->custom_orders_table_usage_is_enabled();
+ if ( ! $this->hpos_in_use ) {
+ $this->cpt_in_use = \WC_Order_Data_Store_CPT::class === \WC_Data_Store::load( 'order' )->get_current_class_name();
+ }
+
+ $this->data_synchronizer = $data_synchronizer;
+ }
+
+ /**
+ * Get the maximum age for debug logs before cleanup, in seconds.
+ * Returns 0 if cleanup is disabled via filter.
+ *
+ * @return int
+ */
+ private function get_max_age_in_seconds(): int {
+ /**
+ * Filter the retention period for place-order debug logs cleanup.
+ * Return 0 to disable cleanup entirely.
+ *
+ * @param int $max_age_in_seconds The maximum age in seconds before cleanup. Default 3 days.
+ *
+ * @since 10.7.0
+ */
+ return absint( apply_filters( 'woocommerce_cleanup_order_debug_logs_max_age', 3 * DAY_IN_SECONDS ) );
+ }
+
+ /**
+ * Run all cleanup tasks: dangling order meta and old log files.
+ *
+ * @since 10.7.0
+ */
+ public function cleanup(): void {
+ $max_age = $this->get_max_age_in_seconds();
+
+ if ( 0 === $max_age ) {
+ return;
+ }
+
+ // Dangling orders have `_debug_log_source` meta but no `_debug_log_source_pending_deletion`.
+ $dangling_orders = $this->get_dangling_orders( $max_age );
+ $this->clear_logs_and_delete_meta( $dangling_orders );
+
+ // Old log files are those that are older than the given max age.
+ $this->cleanup_old_log_files( $max_age );
+ }
+
+ /**
+ * Delete place-order-debug-* log files from the filesystem.
+ *
+ * @param int $max_age Maximum age in seconds before a file is eligible for deletion.
+ */
+ private function cleanup_old_log_files( int $max_age ): void {
+ if ( \Automattic\WooCommerce\Utilities\LoggingUtil::get_default_handler() !== \Automattic\WooCommerce\Internal\Admin\Logging\LogHandlerFileV2::class ) {
+ return;
+ }
+
+ $file_controller = wc_get_container()->get( \Automattic\WooCommerce\Internal\Admin\Logging\FileV2\FileController::class );
+ $files = $file_controller->get_files(
+ array(
+ 'source' => 'place-order-debug',
+ 'date_filter' => 'modified',
+ 'date_start' => 1,
+ 'date_end' => time() - $max_age,
+ 'per_page' => self::MAX_FILES_PER_RUN,
+ )
+ );
+
+ if ( ! is_array( $files ) ) {
+ return;
+ }
+
+ foreach ( $files as $file ) {
+ $file->delete();
+ }
+ }
+
+ /**
+ * Clear debug log files and delete associated order meta for the given items.
+ * Deletes both `_debug_log_source` and `_debug_log_source_pending_deletion` meta.
+ *
+ * @since 10.7.0
+ *
+ * @param array $items Associative array of order ID => log source name.
+ *
+ * @return void
+ */
+ public function clear_logs_and_delete_meta( array $items ): void {
+ if ( empty( $items ) ) {
+ return;
+ }
+
+ $logger = wc_get_logger();
+ if ( $logger instanceof WC_Logger ) {
+ foreach ( $items as $source ) {
+ $logger->clear( $source );
+ }
+ }
+
+ $order_ids = array_keys( $items );
+ $this->delete_debug_log_meta_entries( $order_ids );
+ }
+
+ /**
+ * Get orders with `_debug_log_source` meta older than the given max age.
+ *
+ * Orders that also have `_debug_log_source_pending_deletion` will be handled
+ * by the batch processor, but cleaning them up here too is harmless.
+ *
+ * @param int $max_age Maximum age in seconds.
+ *
+ * @return array Associative array of order ID => log source name.
+ */
+ private function get_dangling_orders( int $max_age ): array {
+ if ( ! $this->hpos_in_use && ! $this->cpt_in_use ) {
+ return array();
+ }
+
+ global $wpdb;
+
+ $cutoff_date = gmdate( 'Y-m-d H:i:s', time() - $max_age );
+
+ $meta_table = $this->hpos_in_use ? "{$wpdb->prefix}wc_orders_meta" : $wpdb->postmeta;
+ $order_table = $this->hpos_in_use ? "{$wpdb->prefix}wc_orders" : $wpdb->posts;
+ $id_column = $this->hpos_in_use ? 'order_id' : 'post_id';
+ $type_column = $this->hpos_in_use ? 'type' : 'post_type';
+ $date_column = $this->hpos_in_use ? 'date_created_gmt' : 'post_date_gmt';
+
+ // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
+ $rows = $wpdb->get_results(
+ $wpdb->prepare(
+ "SELECT m.{$id_column} as order_id, m.meta_value
+ FROM {$meta_table} m
+ INNER JOIN {$order_table} o ON m.{$id_column} = o.id
+ WHERE m.meta_key = %s
+ AND o.{$type_column} = %s
+ AND o.{$date_column} < %s
+ LIMIT %d",
+ '_debug_log_source',
+ 'shop_order',
+ $cutoff_date,
+ self::MAX_ORDERS_PER_RUN
+ ),
+ ARRAY_A
+ );
+ // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
+
+ return array_column( $rows, 'meta_value', 'order_id' );
+ }
+
+ /**
+ * Delete `_debug_log_source` and `_debug_log_source_pending_deletion` meta entries for the given order IDs
+ * from the authoritative table and the backup table (when data sync is enabled).
+ *
+ * @param array $order_ids Array of order IDs to delete meta for.
+ */
+ private function delete_debug_log_meta_entries( array $order_ids ): void {
+ global $wpdb;
+
+ $tables = array(
+ array(
+ 'table' => $this->hpos_in_use ? "{$wpdb->prefix}wc_orders_meta" : $wpdb->postmeta,
+ 'id_column' => $this->hpos_in_use ? 'order_id' : 'post_id',
+ ),
+ );
+
+ if ( $this->data_synchronizer->data_sync_is_enabled() ) {
+ $tables[] = array(
+ 'table' => $this->hpos_in_use ? $wpdb->postmeta : "{$wpdb->prefix}wc_orders_meta",
+ 'id_column' => $this->hpos_in_use ? 'post_id' : 'order_id',
+ );
+ }
+
+ $id_placeholders = implode( ',', array_fill( 0, count( $order_ids ), '%d' ) );
+
+ foreach ( $tables as $table_config ) {
+ // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
+ $wpdb->query(
+ $wpdb->prepare(
+ "DELETE FROM {$table_config['table']}
+ WHERE {$table_config['id_column']} IN ({$id_placeholders})
+ AND meta_key IN (%s, %s)",
+ array_merge( $order_ids, array( '_debug_log_source', '_debug_log_source_pending_deletion' ) )
+ )
+ );
+ // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
+ }
+ }
+}
diff --git a/plugins/woocommerce/src/Internal/Logging/OrderLogsDeletionProcessor.php b/plugins/woocommerce/src/Internal/Logging/OrderLogsDeletionProcessor.php
index 175634fd0ad..ba3957da5e6 100644
--- a/plugins/woocommerce/src/Internal/Logging/OrderLogsDeletionProcessor.php
+++ b/plugins/woocommerce/src/Internal/Logging/OrderLogsDeletionProcessor.php
@@ -6,7 +6,6 @@ namespace Automattic\WooCommerce\Internal\Logging;
use Automattic\WooCommerce\Internal\BatchProcessing\BatchProcessorInterface;
use Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController;
-use Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer;
use Automattic\WooCommerce\Proxies\LegacyProxy;
use Automattic\WooCommerce\Utilities\StringUtil;
@@ -44,11 +43,11 @@ class OrderLogsDeletionProcessor implements BatchProcessorInterface {
private LegacyProxy $legacy_proxy;
/**
- * The instance of DataSynchronizer to use.
+ * The instance of OrderLogsCleanupHelper to use.
*
- * @var DataSynchronizer
+ * @var OrderLogsCleanupHelper
*/
- private DataSynchronizer $data_synchronizer;
+ private OrderLogsCleanupHelper $order_logs_cleanup_helper;
/**
* Initialize the instance.
@@ -56,18 +55,18 @@ class OrderLogsDeletionProcessor implements BatchProcessorInterface {
*
* @param CustomOrdersTableController $hpos_controller The instance of CustomOrdersTableController to use.
* @param LegacyProxy $legacy_proxy The instance of LegacyProxy to use.
- * @param DataSynchronizer $data_synchronizer The instance of DataSynchronizer to use.
+ * @param OrderLogsCleanupHelper $order_logs_cleanup_helper The instance of OrderLogsCleanupHelper to use.
*
* @internal
*/
- final public function init( CustomOrdersTableController $hpos_controller, LegacyProxy $legacy_proxy, DataSynchronizer $data_synchronizer ) {
+ final public function init( CustomOrdersTableController $hpos_controller, LegacyProxy $legacy_proxy, OrderLogsCleanupHelper $order_logs_cleanup_helper ) {
$this->hpos_in_use = $hpos_controller->custom_orders_table_usage_is_enabled();
if ( ! $this->hpos_in_use ) {
$this->cpt_in_use = \WC_Order_Data_Store_CPT::class === \WC_Data_Store::load( 'order' )->get_current_class_name();
}
- $this->legacy_proxy = $legacy_proxy;
- $this->data_synchronizer = $data_synchronizer;
+ $this->legacy_proxy = $legacy_proxy;
+ $this->order_logs_cleanup_helper = $order_logs_cleanup_helper;
}
/**
@@ -235,52 +234,15 @@ class OrderLogsDeletionProcessor implements BatchProcessorInterface {
return;
}
- $logger = $this->legacy_proxy->call_function( 'wc_get_logger' );
+ $items = array();
foreach ( $batch as $item ) {
if ( ! is_array( $item ) || ! isset( $item['meta_value'] ) || ! isset( $item['order_id'] ) ) {
throw new \Exception( "\$batch must be an array of arrays, each having a 'meta_value' key and an 'order_id' key" );
}
- if ( $logger instanceof \WC_Logger ) {
- $logger->clear( $item['meta_value'] );
- }
- }
-
- $order_ids = array_map( 'absint', array_column( $batch, 'order_id' ) );
-
- // Delete from the authoritative meta table.
- $this->delete_debug_log_source_meta_entries( true, $order_ids );
-
- if ( $this->data_synchronizer->data_sync_is_enabled() ) {
- // When HPOS data sync is enabled we need to manually delete the entries in the backup meta table too,
- // otherwise the next sync process will restore the rows we just deleted from the authoritative meta table.
- $this->delete_debug_log_source_meta_entries( false, $order_ids );
+ $items[ $item['order_id'] ] = $item['meta_value'];
}
- }
- /**
- * Delete meta entries for the given order IDs.
- *
- * @param bool $from_authoritative_table True to delete from the authoritative table, false for the backup table.
- * @param array $order_ids Array of order IDs to delete.
- */
- private function delete_debug_log_source_meta_entries( bool $from_authoritative_table, array $order_ids ): void {
- global $wpdb;
-
- $use_hpos_table = $this->hpos_in_use === $from_authoritative_table;
- $table_name = $use_hpos_table ? "{$wpdb->prefix}wc_orders_meta" : $wpdb->postmeta;
- $id_column_name = $use_hpos_table ? 'order_id' : 'post_id';
- $placeholders = implode( ',', array_fill( 0, count( $order_ids ), '%d' ) );
-
- // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
- $wpdb->query(
- $wpdb->prepare(
- "DELETE FROM {$table_name}
- WHERE {$id_column_name} IN ({$placeholders})
- AND meta_key = %s",
- array_merge( $order_ids, array( '_debug_log_source_pending_deletion' ) )
- )
- );
- // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
+ $this->order_logs_cleanup_helper->clear_logs_and_delete_meta( $items );
}
/**
diff --git a/plugins/woocommerce/tests/php/src/Internal/Logging/OrderLogsDeletionProcessorTest.php b/plugins/woocommerce/tests/php/src/Internal/Logging/OrderLogsCleanupTest.php
similarity index 75%
rename from plugins/woocommerce/tests/php/src/Internal/Logging/OrderLogsDeletionProcessorTest.php
rename to plugins/woocommerce/tests/php/src/Internal/Logging/OrderLogsCleanupTest.php
index 213ee8c05d6..8ddc5755ca9 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Logging/OrderLogsDeletionProcessorTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Logging/OrderLogsCleanupTest.php
@@ -4,7 +4,11 @@ declare( strict_types=1 );
namespace Automattic\WooCommerce\Tests\Internal\Logging;
+use Automattic\WooCommerce\Internal\Admin\Logging\FileV2\FileController;
+use Automattic\WooCommerce\Internal\Admin\Logging\LogHandlerFileV2;
+use Automattic\WooCommerce\Internal\Admin\Logging\Settings;
use Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer;
+use Automattic\WooCommerce\Internal\Logging\OrderLogsCleanupHelper;
use Automattic\WooCommerce\Internal\Logging\OrderLogsDeletionProcessor;
use Automattic\WooCommerce\Proxies\LegacyProxy;
use Automattic\WooCommerce\RestApi\UnitTests\Helpers\OrderHelper;
@@ -12,9 +16,9 @@ use Automattic\WooCommerce\RestApi\UnitTests\HPOSToggleTrait;
use Automattic\WooCommerce\Testing\Tools\TestingContainer;
/**
- * Tests for the OrderLogsDeletionProcessor class.
+ * Tests for the OrderLogsDeletionProcessor and OrderLogsCleanupHelper classes.
*/
-class OrderLogsDeletionProcessorTest extends \WC_Unit_Test_Case {
+class OrderLogsCleanupTest extends \WC_Unit_Test_Case {
use HPOSToggleTrait;
/**
@@ -38,6 +42,13 @@ class OrderLogsDeletionProcessorTest extends \WC_Unit_Test_Case {
*/
private OrderLogsDeletionProcessor $sut;
+ /**
+ * The cleanup helper instance.
+ *
+ * @var OrderLogsCleanupHelper
+ */
+ private OrderLogsCleanupHelper $sut_cleanup_helper;
+
/**
* The DI container to use.
*
@@ -97,8 +108,13 @@ class OrderLogsDeletionProcessorTest extends \WC_Unit_Test_Case {
global $wpdb;
$wpdb->delete( $wpdb->prefix . 'wc_orders_meta', array( 'meta_key' => '_debug_log_source_pending_deletion' ) );
$wpdb->delete( $wpdb->postmeta, array( 'meta_key' => '_debug_log_source_pending_deletion' ) );
+ $wpdb->delete( $wpdb->prefix . 'wc_orders_meta', array( 'meta_key' => '_debug_log_source' ) );
+ $wpdb->delete( $wpdb->postmeta, array( 'meta_key' => '_debug_log_source' ) );
- $this->sut = $this->container->get( OrderLogsDeletionProcessor::class );
+ self::delete_all_log_files();
+
+ $this->sut = $this->container->get( OrderLogsDeletionProcessor::class );
+ $this->sut_cleanup_helper = $this->container->get( OrderLogsCleanupHelper::class );
$this->register_legacy_proxy_function_mocks(
array(
@@ -114,6 +130,7 @@ class OrderLogsDeletionProcessorTest extends \WC_Unit_Test_Case {
* Runs after each test.
*/
public function tearDown(): void {
+ self::delete_all_log_files();
parent::tearDown();
if ( $this->data_store_filter_callback ) {
remove_filter( 'woocommerce_order_data_store', $this->data_store_filter_callback, 99999 );
@@ -441,6 +458,81 @@ class OrderLogsDeletionProcessorTest extends \WC_Unit_Test_Case {
return $order_ids;
}
+ /**
+ * @testdox cleanup() deletes old place-order-debug log files whose modification date is at least 3 days in the past, but keeps recent ones.
+ */
+ public function test_cleanup_deletes_old_log_files_but_keeps_recent_ones(): void {
+ $handler = new LogHandlerFileV2();
+ $file_controller = wc_get_container()->get( FileController::class );
+
+ $handler->handle( time(), 'debug', 'old log entry', array( 'source' => 'place-order-debug-old' ) );
+ $handler->handle( time(), 'debug', 'recent log entry', array( 'source' => 'place-order-debug-recent' ) );
+
+ $old_files = $file_controller->get_files( array( 'source' => 'place-order-debug-old' ) );
+ $this->assertCount( 1, $old_files );
+
+ // Backdate the "old" file's modification time to 4 days ago.
+ touch( $old_files[0]->get_path(), time() - 4 * DAY_IN_SECONDS ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_touch
+
+ $recent_files = $file_controller->get_files( array( 'source' => 'place-order-debug-recent' ) );
+ $this->assertCount( 1, $recent_files );
+
+ $this->sut_cleanup_helper->cleanup();
+
+ $this->assertCount( 0, $file_controller->get_files( array( 'source' => 'place-order-debug-old' ) ) );
+ $this->assertCount( 1, $file_controller->get_files( array( 'source' => 'place-order-debug-recent' ) ) );
+ }
+
+ /**
+ * @testdox cleanup() does not touch orders that have _debug_log_source_pending_deletion meta (handled by the batch processor) even if older than 3 days.
+ *
+ * @testWith [true]
+ * [false]
+ *
+ * @param bool $with_hpos Test with HPOS active or not.
+ */
+ public function test_cleanup_does_not_touch_orders_with_pending_deletion_meta( bool $with_hpos ): void {
+ $this->setup_hpos_and_reset_container( $with_hpos );
+
+ $order = OrderHelper::create_order();
+ $order->set_date_created( strtotime( '-5 days' ) );
+ $order->add_meta_data( '_debug_log_source_pending_deletion', 'place-order-debug-batch', true );
+ $order->save();
+
+ $this->sut_cleanup_helper->cleanup();
+
+ $this->assertEquals( 1, $this->sut->get_total_pending_count() );
+ }
+
+ /**
+ * @testdox cleanup() deletes _debug_log_source meta only from orders older than 3 days and leaves recent ones untouched.
+ *
+ * @testWith [true]
+ * [false]
+ *
+ * @param bool $with_hpos Test with HPOS active or not.
+ */
+ public function test_cleanup_deletes_stale_debug_log_source_meta_only_when_old( bool $with_hpos ): void {
+ $this->setup_hpos_and_reset_container( $with_hpos );
+
+ $old_order = OrderHelper::create_order();
+ $old_order->set_date_created( strtotime( '-5 days' ) );
+ $old_order->add_meta_data( '_debug_log_source', 'place-order-debug-stale', true );
+ $old_order->save();
+
+ $recent_order = OrderHelper::create_order();
+ $recent_order->add_meta_data( '_debug_log_source', 'place-order-debug-fresh', true );
+ $recent_order->save();
+
+ $this->sut_cleanup_helper->cleanup();
+
+ $old_order_reloaded = wc_get_order( $old_order->get_id() );
+ $this->assertEmpty( $old_order_reloaded->get_meta( '_debug_log_source' ) );
+
+ $recent_order_reloaded = wc_get_order( $recent_order->get_id() );
+ $this->assertEquals( 'place-order-debug-fresh', $recent_order_reloaded->get_meta( '_debug_log_source' ) );
+ }
+
/**
* Initialize HPOS and reset the DI container resolutions
* (resetting the container is needed because the tested class checks for HPOS activation
@@ -451,6 +543,24 @@ class OrderLogsDeletionProcessorTest extends \WC_Unit_Test_Case {
private function setup_hpos_and_reset_container( bool $enable_hpos ) {
$this->toggle_cot_feature_and_usage( $enable_hpos );
$this->container->reset_all_resolved();
- $this->sut = $this->container->get( OrderLogsDeletionProcessor::class );
+ $this->sut = $this->container->get( OrderLogsDeletionProcessor::class );
+ $this->sut_cleanup_helper = $this->container->get( OrderLogsCleanupHelper::class );
+ }
+
+ /**
+ * Delete all place-order-debug log files using the FileV2 controller.
+ */
+ private static function delete_all_log_files(): void {
+ $file_controller = wc_get_container()->get( FileController::class );
+ $files = $file_controller->get_files(
+ array(
+ 'source' => 'place-order-debug',
+ 'per_page' => 1000,
+ )
+ );
+
+ if ( is_array( $files ) && ! empty( $files ) ) {
+ $file_controller->delete_files( array_map( fn( $file ) => $file->get_file_id(), $files ) );
+ }
}
}