From 00a34e8e4f9f36ee72adec31f1a24131defa8e56 Mon Sep 17 00:00:00 2001 From: David Stone Date: Thu, 30 Apr 2026 00:35:12 -0600 Subject: [PATCH] fix: replace sed dependency with pure PHP in replace_db_prefix() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #1013 The replace_db_prefix() method previously called WP_CLI::launch() with sed commands for database prefix replacement. This failed in web/AJAX context because: - WP_CLI::launch() is not available for sed operations in web context - check_for_sed_presence() itself called WP_CLI::launch() and crashed Changes: - Remove check_for_sed_presence(true) call from tables() — no longer needed since sed is no longer used - Rewrite replace_db_prefix() to process the SQL file line by line using PHP's str_replace(), writing to a temp file then renaming, avoiding any shell/sed dependency - Works correctly in both CLI and web/AJAX contexts --- .../commands/class-mu-migration-import.php | 44 ++++++++++++------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/inc/site-exporter/mu-migration/includes/commands/class-mu-migration-import.php b/inc/site-exporter/mu-migration/includes/commands/class-mu-migration-import.php index 7de11c3a2..c6e123928 100644 --- a/inc/site-exporter/mu-migration/includes/commands/class-mu-migration-import.php +++ b/inc/site-exporter/mu-migration/includes/commands/class-mu-migration-import.php @@ -289,9 +289,6 @@ public function tables($args = [], $assoc_args = [], $verbose = true) { $wu_site_exporter_site_id = $this->assoc_args['blog_id']; - // Terminates the script if sed is not installed. - $this->check_for_sed_presence(true); - // Replaces the db prefix and saves back the modifications to the sql file. if ( ! empty($this->assoc_args['new_prefix']) ) { $this->replace_db_prefix($filename, $this->assoc_args['old_prefix'], $this->assoc_args['new_prefix']); @@ -676,7 +673,11 @@ private function create_new_site($meta_data) { } /** - * Replaces the db_prefix with a new one using sed. + * Replaces the db_prefix with a new one using pure PHP string replacement. + * + * Processes the SQL file line by line to avoid loading the entire file into + * memory, and writes output to a temporary file before replacing the original. + * Works in both CLI and web/AJAX contexts (no sed dependency). * * @param string $filename The filename of the sql file to which the db prefix should be replaced. * @param string $old_db_prefix The db prefix to be replaced. @@ -686,7 +687,7 @@ private function replace_db_prefix($filename, $old_db_prefix, $new_db_prefix) { $new_prefix = $new_db_prefix; if ( ! empty($new_prefix) ) { - $mysql_chunks_regex = [ + $mysql_keywords = [ 'DROP TABLE IF EXISTS', 'CREATE TABLE', 'LOCK TABLES', @@ -697,20 +698,33 @@ private function replace_db_prefix($filename, $old_db_prefix, $new_db_prefix) { 'REFERENCES', ]; - // build sed expressions - $sed_commands = []; - foreach ( $mysql_chunks_regex as $regex ) { - $sed_commands[] = "s/{$regex} `{$old_db_prefix}/{$regex} `{$new_prefix}/g"; - } + $temp_filename = $filename . '.tmp'; + $input = fopen($filename, 'r'); + $output = fopen($temp_filename, 'w'); - foreach ( $sed_commands as $sed_command ) { - $full_command = "sed '$sed_command' -i $filename"; - $sed_result = \WP_CLI::launch($full_command, false, false); + if ( false === $input || false === $output ) { + \WP_CLI::warning(__('Could not open SQL file for prefix replacement', 'mu-migration')); + if ( $input ) { + fclose($input); + } + return; + } - if ( 0 !== $sed_result ) { - \WP_CLI::warning(__('Something went wrong while running sed', 'mu-migration')); + while ( false !== ($line = fgets($input)) ) { + foreach ( $mysql_keywords as $keyword ) { + $line = str_replace( + $keyword . ' `' . $old_db_prefix, + $keyword . ' `' . $new_prefix, + $line + ); } + fwrite($output, $line); } + + fclose($input); + fclose($output); + + rename($temp_filename, $filename); } }