From d689a90ca387952d6c7c52d68856275adb4c4792 Mon Sep 17 00:00:00 2001 From: Antonio Sejas Date: Mon, 16 Mar 2026 20:32:14 +0000 Subject: [PATCH] Make DB_NAME constants removal logic language-agnostic Replace exact string matching with a regex that is strict on PHP define() calls (only matches default values from wp-config-sample.php) but flexible with comments, so translated wp-config.php files are handled correctly. --- .../common/lib/remove-default-db-constants.ts | 58 +++++--- .../tests/remove-default-db-constants.test.ts | 124 +++++++++++++++++- 2 files changed, 163 insertions(+), 19 deletions(-) diff --git a/tools/common/lib/remove-default-db-constants.ts b/tools/common/lib/remove-default-db-constants.ts index 415c46fef8..3fd47f9e40 100644 --- a/tools/common/lib/remove-default-db-constants.ts +++ b/tools/common/lib/remove-default-db-constants.ts @@ -1,23 +1,45 @@ -const DB_SETTINGS_BLOCK = - normalizeLineEndings( `// ** Database settings - You can get this info from your web host ** // -/** The name of the database for WordPress */ -define( 'DB_NAME', 'database_name_here' ); +/** + * Default values for database constants in wp-config-sample.php. + * Only these exact default values will be matched and removed. + */ +const DB_DEFAULTS: Array< [ string, string ] > = [ + [ 'DB_NAME', 'database_name_here' ], + [ 'DB_USER', 'username_here' ], + [ 'DB_PASSWORD', 'password_here' ], + [ 'DB_HOST', 'localhost' ], + [ 'DB_CHARSET', 'utf8mb4' ], + [ 'DB_COLLATE', '' ], +]; -/** Database username */ -define( 'DB_USER', 'username_here' ); +/** + * Builds a regex that matches the default DB settings block in wp-config.php. + * + * The regex is flexible with comments (they may be in any language) but strict + * with PHP code (only matches exact default values from wp-config-sample.php). + * + * Structure matched per constant: + * [optional comment lines] <- flexible (any language) + * define( 'DB_X', 'default_value' ); <- strict (exact match) + * [optional blank lines] + */ +function buildDefaultDbBlockRegex(): RegExp { + // Matches a single-line comment: // ... or a docblock comment: /** ... */ + const commentLine = + '[ \\t]*(?:\\/\\/[^\\r\\n]*|\\/\\*\\*[^*]*(?:\\*(?!\\/)[^*]*)*\\*\\/)[ \\t]*\\r?\\n'; + // Zero or more comment lines before a define + const optionalComments = `(?:${ commentLine })*`; + // Optional blank lines between entries + const blankLines = '(?:[ \\t]*\\r?\\n)*'; -/** Database password */ -define( 'DB_PASSWORD', 'password_here' ); + const definePatterns = DB_DEFAULTS.map( ( [ name, value ] ) => { + const escapedValue = value.replace( /[.*+?^${}()|[\]\\]/g, '\\$&' ); + return `${ optionalComments }[ \\t]*define\\([ \\t]*'${ name }'[ \\t]*,[ \\t]*'${ escapedValue }'[ \\t]*\\)[ \\t]*;[ \\t]*\\r?\\n`; + } ); -/** Database hostname */ -define( 'DB_HOST', 'localhost' ); - -/** Database charset to use in creating database tables. */ -define( 'DB_CHARSET', 'utf8mb4' ); + return new RegExp( definePatterns.join( blankLines ) ); +} -/** The database collate type. Don't change this if in doubt. */ -define( 'DB_COLLATE', '' ); -` ); +const DB_SETTINGS_BLOCK_REGEX = buildDefaultDbBlockRegex(); const REPLACEMENT_COMMENT = normalizeLineEndings( `/** * Database connection information is automatically provided. @@ -36,9 +58,9 @@ export function normalizeLineEndings( content: string ): string { } export function hasDefaultDbBlock( content: string ): boolean { - return content.includes( DB_SETTINGS_BLOCK ); + return DB_SETTINGS_BLOCK_REGEX.test( content ); } export function removeDbConstants( content: string ): string { - return content.replace( DB_SETTINGS_BLOCK, REPLACEMENT_COMMENT + '\n' ); + return content.replace( DB_SETTINGS_BLOCK_REGEX, REPLACEMENT_COMMENT + '\n' ); } diff --git a/tools/common/lib/tests/remove-default-db-constants.test.ts b/tools/common/lib/tests/remove-default-db-constants.test.ts index d858169a87..a3646f0494 100644 --- a/tools/common/lib/tests/remove-default-db-constants.test.ts +++ b/tools/common/lib/tests/remove-default-db-constants.test.ts @@ -35,6 +35,75 @@ define( 'WP_DEBUG', false ); /* That's all, stop editing! Happy publishing. */ ` ); +const WP_CONFIG_WITH_POLISH_COMMENTS = normalizeLineEndings( ` { expect( hasDefaultDbBlock( WP_CONFIG_WITH_DEFAULTS ) ).toBe( true ); } ); + it( 'should return true when comments are in Polish', () => { + expect( hasDefaultDbBlock( WP_CONFIG_WITH_POLISH_COMMENTS ) ).toBe( true ); + } ); + + it( 'should return true when comments are in French', () => { + expect( hasDefaultDbBlock( WP_CONFIG_WITH_FRENCH_COMMENTS ) ).toBe( true ); + } ); + + it( 'should return true when there are no comments at all', () => { + expect( hasDefaultDbBlock( WP_CONFIG_WITH_NO_COMMENTS ) ).toBe( true ); + } ); + it( 'should return false when DB values are custom', () => { expect( hasDefaultDbBlock( WP_CONFIG_WITH_CUSTOM_VALUES ) ).toBe( false ); } ); @@ -133,19 +214,52 @@ describe( 'removeDbConstants', () => { it( 'should remove the entire DB settings block', () => { const result = removeDbConstants( WP_CONFIG_WITH_DEFAULTS ); - expect( result ).not.toContain( '// ** Database settings' ); expect( result ).not.toContain( "define( 'DB_NAME'" ); expect( result ).not.toContain( "define( 'DB_USER'" ); expect( result ).not.toContain( "define( 'DB_PASSWORD'" ); expect( result ).not.toContain( "define( 'DB_HOST'" ); expect( result ).not.toContain( "define( 'DB_CHARSET'" ); expect( result ).not.toContain( "define( 'DB_COLLATE'" ); + } ); + + it( 'should remove comments associated with the DB block', () => { + const result = removeDbConstants( WP_CONFIG_WITH_DEFAULTS ); + + expect( result ).not.toContain( '// ** Database settings' ); expect( result ).not.toContain( 'The name of the database for WordPress' ); expect( result ).not.toContain( 'Database username' ); expect( result ).not.toContain( 'Database password' ); expect( result ).not.toContain( 'Database hostname' ); } ); + it( 'should remove translated comments (Polish)', () => { + const result = removeDbConstants( WP_CONFIG_WITH_POLISH_COMMENTS ); + + expect( result ).not.toContain( "define( 'DB_NAME'" ); + expect( result ).not.toContain( 'Nazwa bazy danych' ); + expect( result ).not.toContain( 'Ustawienia bazy danych' ); + expect( result ).toContain( 'Database connection information is automatically provided' ); + expect( result ).toContain( "$table_prefix = 'wp_'" ); + } ); + + it( 'should remove translated comments (French)', () => { + const result = removeDbConstants( WP_CONFIG_WITH_FRENCH_COMMENTS ); + + expect( result ).not.toContain( "define( 'DB_NAME'" ); + expect( result ).not.toContain( 'Le nom de la base' ); + expect( result ).toContain( 'Database connection information is automatically provided' ); + expect( result ).toContain( "$table_prefix = 'wp_'" ); + } ); + + it( 'should remove defines even without comments', () => { + const result = removeDbConstants( WP_CONFIG_WITH_NO_COMMENTS ); + + expect( result ).not.toContain( "define( 'DB_NAME'" ); + expect( result ).not.toContain( "define( 'DB_USER'" ); + expect( result ).toContain( 'Database connection information is automatically provided' ); + expect( result ).toContain( "$table_prefix = 'wp_'" ); + } ); + it( 'should add the replacement comment block', () => { const result = removeDbConstants( WP_CONFIG_WITH_DEFAULTS ); @@ -179,6 +293,14 @@ describe( 'integration: full migration flow', () => { expect( result ).toContain( 'Database connection information is automatically provided' ); } ); + it( 'should correctly process wp-config.php with translated comments', () => { + expect( hasDefaultDbBlock( WP_CONFIG_WITH_POLISH_COMMENTS ) ).toBe( true ); + + const result = removeDbConstants( WP_CONFIG_WITH_POLISH_COMMENTS ); + expect( result ).toContain( 'Database connection information is automatically provided' ); + expect( hasDefaultDbBlock( result ) ).toBe( false ); + } ); + it( 'should not modify wp-config.php with custom values', () => { expect( hasDefaultDbBlock( WP_CONFIG_WITH_CUSTOM_VALUES ) ).toBe( false ); } );