Skip to content

Commit

Permalink
fix(MysqlDatabase) remove brittle db name validation, fix #667 and #671
Browse files Browse the repository at this point in the history
  • Loading branch information
lucatume committed Nov 24, 2023
1 parent 3189538 commit b6282d9
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 62 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Fixed

- Correctly activate themes during bootstrap.
- Remove brittle database name validation, fix #667 and #671.

#### Changed

Expand Down
10 changes: 2 additions & 8 deletions src/WordPress/Database/MysqlDatabase.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,6 @@ public function __construct(
private string $dbHost,
private string $tablePrefix = 'wp_'
) {
if (!preg_match('/^[a-zA-Z][\w_-]{0,64}$/', $dbName) || str_starts_with('ii', $dbName)) {
throw new DbException(
"Invalid database name: $dbName",
DbException::INVALID_DB_NAME
);
}

$this->dbName = $dbName;
$this->dsnWithoutDbName = DbUtil::dbDsnString(DbUtil::dbDsnMap($dbHost));
$this->dsn = $this->dsnWithoutDbName . ';dbname=' . $dbName;
Expand Down Expand Up @@ -154,7 +147,8 @@ public function drop(): self

public function exists(): bool
{
$result = $this->getPDO()->query("SHOW DATABASES LIKE '{$this->dbName}'", PDO::FETCH_COLUMN, 0);
$query = "SHOW DATABASES WHERE `Database` = '{$this->dbName}'";
$result = $this->getPDO()->query($query, PDO::FETCH_COLUMN, 0);

if ($result === false) {
return false;
Expand Down
55 changes: 55 additions & 0 deletions tests/unit/lucatume/WPBrowser/Events/Module/WPLoaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1873,4 +1873,59 @@ function plugin_2_canary() {}
Assert::assertEquals('theme-1', wp_get_theme()->get_stylesheet());
});
}

public function differentDbNamesProvider(): array
{
return [
'with dashes, underscores and dots' => ['test-db_db.db'],
'only words and numbers' => ['testdb1234567890'],
'all together' => ['test-db_db.db1234567890'],
'mydatabase.dev' => ['mydatabase.dev'],
'my_dbname_n8h96prxar4r' => ['my_dbname_n8h96prxar4r'],
'!funny~db-name' => ['!funny~db-name'],
];
}

/**
* It should correctly load with different database names
*
* @test
* @dataProvider differentDbNamesProvider
*/
public function should_correctly_load_with_different_database_names(string $dbName): void
{
$wpRootDir = FS::tmpDir('wploader_');
$installation = Installation::scaffold($wpRootDir);
$dbHost = Env::get('WORDPRESS_DB_HOST');
$dbUser = Env::get('WORDPRESS_DB_USER');
$dbPassword = Env::get('WORDPRESS_DB_PASSWORD');
$db = new MysqlDatabase($dbName, $dbUser, $dbPassword, $dbHost, 'test_');
$db->drop();
$installation->configure($db);
$installation->install(
'https://wp.local',
'admin',
'password',
'admin@wp.local',
'Test'
);

$this->config = [
'wpRootFolder' => $wpRootDir,
'dbUrl' => $db->getDbUrl()
];
$wpLoader = $this->module();

$this->assertEquals(
$db->getDbName(),
$this->assertInIsolation(static function () use ($wpLoader) {
$wpLoader->_initialize();

Assert::assertTrue(function_exists('do_action'));
Assert::assertInstanceOf(\WP_User::class, wp_get_current_user());

return $wpLoader->getInstallation()->getDb()->getDbName();
})
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,6 @@ class MysqlDatabaseTest extends Unit
use UopzFunctions;
use TmpFilesCleanup;

/**
* It should throw when building with invalid db name
*
* @test
*/
public function should_throw_when_building_with_invalid_db_name(): void
{
$this->expectException(DbException::class);
$this->expectExceptionCode(DbException::INVALID_DB_NAME);

new MysqlDatabase('!invalid~db-name', 'root', 'root', 'localhost');
}

/**
* It should allow getting the db credentials and DSN
*
Expand All @@ -52,8 +39,10 @@ public function should_allow_getting_the_db_credentials_and_dsn(): void
$this->assertEquals('192.1.2.3:4415', $db->getDbHost());
$this->assertEquals('test_', $db->getTablePrefix());
$this->assertEquals('mysql:host=192.1.2.3;port=4415;dbname=test', $db->getDsn());
$this->assertEquals('mysql://bob:secret@192.1.2.3:4415/test',
$db->getDbUrl());
$this->assertEquals(
'mysql://bob:secret@192.1.2.3:4415/test',
$db->getDbUrl()
);
}

/**
Expand All @@ -77,8 +66,10 @@ public function should_build_correctly_from_wp_config_file(): void
$this->assertEquals('192.1.2.3:4415', $db->getDbHost());
$this->assertEquals('test_', $db->getTablePrefix());
$this->assertEquals('mysql:host=192.1.2.3;port=4415;dbname=test', $db->getDsn());
$this->assertEquals('mysql://bob:secret@192.1.2.3:4415/test',
$db->getDbUrl());
$this->assertEquals(
'mysql://bob:secret@192.1.2.3:4415/test',
$db->getDbUrl()
);
}

/**
Expand Down Expand Up @@ -126,21 +117,24 @@ public function should_allow_options_operations(): void
'admin',
'password',
'admin@wp.local',
'Test');
'Test'
);

new Single($wpRootDir, $wpRootDir . '/wp-config.php');

$this->assertEquals('lorem', $db->getOption('non-existent-option', 'lorem'));
foreach ([
'foo' => 'bar',
'bar' => 2389,
'object' => (object)['foo' => 'bar'],
'array' => ['foo' => 'bar'],
'associative array' => ['foo' => 'bar', 'bar' => 'foo'],
'null' => null,
'true' => true,
'false' => false,
] as $name => $value) {
foreach (
[
'foo' => 'bar',
'bar' => 2389,
'object' => (object)['foo' => 'bar'],
'array' => ['foo' => 'bar'],
'associative array' => ['foo' => 'bar', 'bar' => 'foo'],
'null' => null,
'true' => true,
'false' => false,
] as $name => $value
) {
$this->assertEquals(1, $db->updateOption($name, $value));
$this->assertEquals($value, $db->getOption($name));
}
Expand Down
26 changes: 0 additions & 26 deletions tests/unit/lucatume/WPBrowser/WordPress/InstallationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -642,30 +642,4 @@ public function should_throw_if_word_press_installation_cannot_be_found_in_direc

Installation::findInDir($dir);
}

/**
* It should find WordPress installation in directory
*
* @test
*/
public function should_find_word_press_installation_in_directory(): void
{
if (PHP_VERSION < 8.0) {
$this->markTestSkipped('PHP 8.0 required.');
}

$db = new MysqlDatabase(
Random::dbName(),
Env::get('WORDPRESS_DB_USER'),
Env::get('WORDPRESS_DB_PASSWORD'),
Env::get('WORDPRESS_DB_HOST')
);
$dir = (new BedrockProject($db, 'http://example.com'))->scaffold(FS::tmpDir('installation_'));

$installation = Installation::findInDir($dir);

$this->assertInstanceOf(Installation::class, $installation);
$this->assertInstanceOf(Configured::class, $installation->getState());
$this->assertEquals($dir . '/web/wp/', $installation->getRootDir());
}
}

0 comments on commit b6282d9

Please sign in to comment.