lation_levels(), true ) ) { throw new \Exception( 'Invalid database transaction isolation level name ' . $transaction_isolation_level ); } } /** * Commit the current database transaction. * * @return bool True on success, false on error. */ private function commit_transaction(): bool { return $this->db_query( 'COMMIT' ); } /** * Rollback the current database transaction. * * @return bool True on success, false on error. */ private function rollback_transaction(): bool { return $this->db_query( 'ROLLBACK' ); } /** * Execute a database query and log any errors. * * @param string $query The SQL query to execute. * @return bool True if the query succeeded, false if there were errors. */ private function db_query( string $query ): bool { $wpdb = WC()->get_global( 'wpdb' ); try { // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared $wpdb->query( $query ); } catch ( \Exception $exception ) { $exception_class = get_class( $exception ); $this->error_logger->error( "PostsToOrdersMigrationController: when executing $query: ($exception_class) {$exception->getMessage()}, {$exception->getTraceAsString()}", array( 'source' => self::LOGS_SOURCE_NAME, 'exception' => $exception, ) ); return false; } $error = $wpdb->last_error; if ( '' !== $error ) { $this->error_logger->error( "PostsToOrdersMigrationController: when executing $query: $error", array( 'source' => self::LOGS_SOURCE_NAME, 'error' => $error, ) ); return false; } return true; } /** * Performs one step of the migration for a set of order posts using one given migration class. * All database errors and exceptions are logged. * * @param object $migration_class The migration class to use, must have a `process_migration_batch_for_ids(array of ids)` method. * @param array $order_post_ids List of post IDs of the orders to migrate. * @return bool True if errors were logged, false otherwise. */ private function do_orders_migration_step( object $migration_class, array $order_post_ids ): bool { $result = $migration_class->process_migration_batch_for_ids( $order_post_ids ); $errors = array_unique( $result['errors'] ); $exception = $result['exception']; if ( null === $exception && empty( $errors ) ) { return false; } $migration_class_name = ( new \ReflectionClass( $migration_class ) )->getShortName(); $batch = ArrayUtil::to_ranges_string( $order_post_ids ); if ( null !== $exception ) { $exception_class = get_class( $exception ); $this->error_logger->error( "$migration_class_name: when processing ids $batch: ($exception_class) {$exception->getMessage()}, {$exception->getTraceAsString()}", array( 'source' => self::LOGS_SOURCE_NAME, 'ids' => $order_post_ids, 'exception' => $exception, ) ); } foreach ( $errors as $error ) { $this->error_logger->error( "$migration_class_name: when processing ids $batch: $error", array( 'source' => self::LOGS_SOURCE_NAME, 'ids' => $order_post_ids, 'error' => $error, ) ); } return true; } /** * Verify whether the given order IDs were migrated properly or not. * * @param array $order_post_ids Order IDs. * * @return array Array of failed IDs along with columns. */ public function verify_migrated_orders( array $order_post_ids ): array { $errors = array(); foreach ( $this->all_migrators as $migrator ) { if ( method_exists( $migrator, 'verify_migrated_data' ) ) { $errors = $errors + $migrator->verify_migrated_data( $order_post_ids ); } } return $errors; } /** * Migrates an order from the posts table to the custom orders tables. * * @param int $order_post_id Post ID of the order to migrate. */ public function migrate_order( int $order_post_id ): void { $this->migrate_orders( array( $order_post_id ) ); } }