From a1eb010886f2f6a2f970bdd015fb0adbefe142e0 Mon Sep 17 00:00:00 2001 From: Luca Tumedei Date: Wed, 11 Sep 2024 09:55:18 +0200 Subject: [PATCH] transpile #755 --- src/Module/WPLoader.php | 4 +- src/WordPress/LoadSandbox.php | 24 +++- tests/_support/Traits/InstallationMocks.php | 21 +-- .../WPBrowser/Module/WPLoaderLoadOnlyTest.php | 126 ++++++++++++++++++ 4 files changed, 165 insertions(+), 10 deletions(-) diff --git a/src/Module/WPLoader.php b/src/Module/WPLoader.php index 377e91464..a032f289b 100644 --- a/src/Module/WPLoader.php +++ b/src/Module/WPLoader.php @@ -647,11 +647,13 @@ public function _loadWordPress(?bool $loadOnly = null): void $this->loadConfigFiles(); if ($loadOnly) { + putenv('WPBROWSER_LOAD_ONLY=1'); Dispatcher::dispatch(self::EVENT_BEFORE_LOADONLY, $this); $loadSandbox = new LoadSandbox($this->installation->getWpRootDir(), $this->config['domain']); - $loadSandbox->load(); + $loadSandbox->load($this->db); Dispatcher::dispatch(self::EVENT_AFTER_LOADONLY, $this); } else { + putenv('WPBROWSER_LOAD_ONLY=0'); $this->installAndBootstrapInstallation(); } diff --git a/src/WordPress/LoadSandbox.php b/src/WordPress/LoadSandbox.php index fda309be8..e74ecd39e 100644 --- a/src/WordPress/LoadSandbox.php +++ b/src/WordPress/LoadSandbox.php @@ -2,6 +2,11 @@ namespace lucatume\WPBrowser\WordPress; +use lucatume\WPBrowser\Utils\MonkeyPatch; +use lucatume\WPBrowser\Utils\Property; +use lucatume\WPBrowser\WordPress\Database\DatabaseInterface; +use lucatume\WPBrowser\WordPress\Database\MysqlDatabase; + class LoadSandbox { /** @@ -30,7 +35,7 @@ public function __construct(string $wpRootDir, string $domain) /** * @throws InstallationException */ - public function load(): void + public function load(?DatabaseInterface $db = null): void { $this->setUpServerVars(); PreloadFilters::addFilter('wp_fatal_error_handler_enabled', [$this, 'returnFalse'], 100); @@ -39,9 +44,26 @@ public function load(): void // Setting the `chunk_size` to `0` means the function will only be called when the output buffer is closed. ob_start([$this, 'obCallback'], 0); + if ($db instanceof MysqlDatabase) { + define('DB_NAME', $db->getDbName()); + define('DB_USER', $db->getDbUser()); + define('DB_PASSWORD', $db->getDbPassword()); + define('DB_HOST', $db->getDbHost()); + + // Silence errors about the redeclaration of the above `DB_` constants. + $previousErrorHandler = set_error_handler(static function ($errno, $errstr) { + return $errno === E_WARNING + && preg_match('/^Constant DB_(NAME|USER|PASSWORD|HOST) already defined/i', $errstr); + }); + } + // Exceptions thrown during loading are not wrapped on purpose to remove debug overhead. include_once $this->wpRootDir . '/wp-load.php'; + if (!empty($previousErrorHandler)) { + set_error_handler($previousErrorHandler); + } + ob_end_clean(); // If this is reached, then WordPress has loaded correctly. remove_filter('wp_fatal_error_handler_enabled', [$this, 'returnFalse'], 100); diff --git a/tests/_support/Traits/InstallationMocks.php b/tests/_support/Traits/InstallationMocks.php index e28c0351b..588625d6e 100644 --- a/tests/_support/Traits/InstallationMocks.php +++ b/tests/_support/Traits/InstallationMocks.php @@ -12,12 +12,17 @@ trait InstallationMocks /** * @return array{0: string, 1: string} */ - private function makeMockConfiguredInstallation(string $phpExtra = ''): array + private function makeMockConfiguredInstallation(string $phpExtra = '', array $overrides = []): array { - $dbUser = Env::get('WORDPRESS_DB_USER'); - $dbPassword = Env::get('WORDPRESS_DB_PASSWORD'); - $dbLocalhostPort = Env::get('WORDPRESS_DB_LOCALHOST_PORT'); - $dbName = Env::get('WORDPRESS_DB_NAME'); + $dbUser = $overrides['dbUser'] ?? Env::get('WORDPRESS_DB_USER'); + $dbPassword = $overrides['dbPassword'] ?? Env::get('WORDPRESS_DB_PASSWORD'); + if(!isset($overrides['dbHost'])){ + $dbLocalhostPort = $overrides['dbLocalhostPort'] ?? Env::get('WORDPRESS_DB_LOCALHOST_PORT'); + $dbHost = '127.0.0.1:' . $dbLocalhostPort; + } else { + $dbHost = $overrides['dbHost']; + } + $dbName = $overrides['dbName'] ?? Env::get('WORDPRESS_DB_NAME'); $wpRootFolder = FS::tmpDir('wploader_', [ 'wp-includes' => [ 'version.php' => << 'assertTrue($module->_didLoadWordPress()); }); } + + public function testWillDefineDBConstantsWhenLoadOnlyTrue(): void{ + [$wpRootFolder] = $this->makeMockConfiguredInstallation('', [ + 'dbUser' => 'production_user', + 'dbPassword' => 'production_password', + 'dbHost' => '10.0.0.1:8876', + 'dbName' => 'test_db', + ]); + file_put_contents($wpRootFolder . '/wp-load.php', ' $testDbUrl, + 'wpRootFolder' => $wpRootFolder, + 'loadOnly' => true, + ]); + + Fork::executeClosure(function () use ($testDbName, $testDbHost, $testDbPassword, $testDbUser, $module) { + // WordPress' functions are stubbed by wordpress-stubs in unit tests: override them to do something. + $did_actions = []; + uopz_set_return('do_action', static function ($action) use (&$did_actions) { + $did_actions[$action] = true; + }, true); + uopz_set_return('did_action', static function ($action) use (&$did_actions) { + return isset($did_actions[$action]); + }, true); + // Partial mocking the function that would load WordPress. + uopz_set_return(WPLoader::class, 'installAndBootstrapInstallation', function () { + return true; + }, true); + + $module->_initialize(); + $module->_beforeSuite(); + + $this->assertTrue($module->_didLoadWordPress()); + $this->assertEquals($testDbUser, DB_USER); + $this->assertEquals($testDbPassword, DB_PASSWORD); + $this->assertEquals($testDbHost, DB_HOST); + $this->assertEquals($testDbName, DB_NAME); + $this->assertEquals('1', getenv('WPBROWSER_LOAD_ONLY')); + }); + } + + public function testWillLoadConfigFileWhenLoadOnlyTrue(): void{ + [$wpRootFolder, $dbUrl] = $this->makeMockConfiguredInstallation(); + $configDir = FS::tmpDir('config_', [ + 'test-config.php' => ' $dbUrl, + 'wpRootFolder' => $wpRootFolder, + 'loadOnly' => true, + 'configFile' => $configDir . '/test-config.php' + ]); + + Fork::executeClosure(function () use ($module) { + // WordPress' functions are stubbed by wordpress-stubs in unit tests: override them to do something. + $did_actions = []; + uopz_set_return('do_action', static function ($action) use (&$did_actions) { + $did_actions[$action] = true; + }, true); + uopz_set_return('did_action', static function ($action) use (&$did_actions) { + return isset($did_actions[$action]); + }, true); + // Partial mocking the function that would load WordPress. + uopz_set_return(WPLoader::class, 'installAndBootstrapInstallation', function () { + return true; + }, true); + + $module->_initialize(); + $module->_beforeSuite(); + + $this->assertTrue($module->_didLoadWordPress()); + $this->assertTrue(defined('TEST_CONFIG')); + }); + } + + public function testWillLoadMultipleConfigFilesWhenLoadOnlyTrue(): void{ + [$wpRootFolder, $dbUrl] = $this->makeMockConfiguredInstallation(); + $configDir = FS::tmpDir('config_', [ + 'test-config.php' => ' ' $dbUrl, + 'wpRootFolder' => $wpRootFolder, + 'loadOnly' => true, + 'configFile' => [$configDir . '/test-config.php', $configDir . '/test-config2.php'] + ]); + + Fork::executeClosure(function () use ($module) { + // WordPress' functions are stubbed by wordpress-stubs in unit tests: override them to do something. + $did_actions = []; + uopz_set_return('do_action', static function ($action) use (&$did_actions) { + $did_actions[$action] = true; + }, true); + uopz_set_return('did_action', static function ($action) use (&$did_actions) { + return isset($did_actions[$action]); + }, true); + // Partial mocking the function that would load WordPress. + uopz_set_return(WPLoader::class, 'installAndBootstrapInstallation', function () { + return true; + }, true); + + $module->_initialize(); + $module->_beforeSuite(); + + $this->assertTrue($module->_didLoadWordPress()); + $this->assertTrue(defined('TEST_CONFIG')); + $this->assertTrue(defined('TEST_CONFIG2')); + }); + } }