Skip to content

Commit

Permalink
fix(Module/WPLoader) ensure active_plugins
Browse files Browse the repository at this point in the history
Depending on the set up, some plugins might deactivate, or activate,
other plugins during their activation. This ensures the plugins set in
the `plugins` configuration parameter of the `WPLoader` module will
always be loaded, no matter what other plugins might do during their
activation.
  • Loading branch information
lucatume committed Dec 9, 2024
1 parent 52a60fa commit de3f631
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 10 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).

## [unreleased] Unreleased

### Fixed

- Ensure plugin activation is respected indifferent of plugins that might deactivate others during activation.

## [4.4.0] 2024-12-08;

## Added
Expand Down
16 changes: 11 additions & 5 deletions src/Module/WPLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ public function _initialize(): void
if (empty($config['dbHost']) && str_starts_with($config['dbName'], codecept_root_dir())) {
$dbFile = (array_reverse(explode(DIRECTORY_SEPARATOR, $config['dbName']))[0]);
$dbDir = rtrim(str_replace($dbFile, '', $config['dbName']), DIRECTORY_SEPARATOR);
$db = new SqliteDatabase($dbDir, $dbFile);
$db = new SqliteDatabase($dbDir, $dbFile, $config['tablePrefix']);
} else {
$db = new MysqlDatabase(
$config['dbName'],
Expand Down Expand Up @@ -1140,18 +1140,24 @@ private function activatePluginsTheme(array $plugins): array
$database->updateOption('stylesheet', $database->getOption('stylesheet'));
}

// Flush the cache to force the refetch of the options' value.
wp_cache_delete('alloptions', 'options');

// Do not include external plugins, it would create issues at this stage.
$pluginsDir = $this->getPluginsFolder();

return array_values(
$activePlugins = array_values(
array_filter(
$plugins,
static fn(string $plugin) => is_file($pluginsDir . "/$plugin")
)
);

// During activation some plugins could deactivate other plugins: protect from it.
$database->updateOption('active_plugins', $activePlugins);

// Flush the cache to force the refetch of the options' value.
wp_cache_delete('alloptions', 'options');


return $activePlugins;
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/Process/SerializableThrowable.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class SerializableThrowable
private array $trace;
private string $file;
private int $line;
private int $code;
private int|string $code;
private string $message;
private bool $colorize = true;

Expand All @@ -42,7 +42,7 @@ public function __construct(Throwable $throwable)
* colorize: bool,
* throwable: Throwable,
* message: string,
* code: int,
* code: int|string,
* file: string,
* line: int,
* trace: array<int,array<string,mixed>>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,83 @@ public function test_loads_plugins_from_default_location_correctly(): void
/**
* Plugin Name: Test One
*/
function test_one_loaded(){}
PHP
)) {
throw new \RuntimeException('Unable to create test plugin file for plugin test-one');
}
if (!mkdir($projectDir . '/wp-content/plugins/test-two', 0777, true)) {
throw new \RuntimeException('Unable to create test directory for plugin test-two');
}
if (!file_put_contents(
$projectDir . '/wp-content/plugins/test-two/plugin.php',
<<< PHP
<?php
/**
* Plugin Name: Test Two
*/
function test_one_loaded(){}
function test_two_loaded(){}
PHP
)) {
throw new \RuntimeException('Unable to create test plugin file for plugin test-two');
}

$this->config = [
'wpRootFolder' => $projectDir,
'dbUrl' => $installationDb->getDbUrl(),
'tablePrefix' => 'test_',
'plugins' => [
'test-one/plugin.php',
'test-two/plugin.php',
]
];
$wpLoader = $this->module();
$projectDirname = basename($projectDir);

$this->assertInIsolation(
static function () use ($wpLoader, $projectDir) {
chdir($projectDir);

$wpLoader->_initialize();

Assert::assertTrue(function_exists('test_one_loaded'));
Assert::assertTrue(function_exists('test_two_loaded'));
Assert::assertEquals(
['test-one/plugin.php','test-two/plugin.php'],
get_option('active_plugins')
);
global $wpdb;
Assert::assertEquals(
serialize(['test-one/plugin.php','test-two/plugin.php']),
$wpdb->get_var("select option_value from {$wpdb->prefix}options where option_name = 'active_plugins'")
);
}
);
}

public function test_loads_plugins_and_ensures_them_loaded(): void
{
$projectDir = FS::tmpDir('wploader_');
$installation = Installation::scaffold($projectDir);
$dbName = Random::dbName();
$dbHost = Env::get('WORDPRESS_DB_HOST');
$dbUser = Env::get('WORDPRESS_DB_USER');
$dbPassword = Env::get('WORDPRESS_DB_PASSWORD');
$installationDb = new MysqlDatabase($dbName, $dbUser, $dbPassword, $dbHost, 'wp_');
if (!mkdir($projectDir . '/wp-content/plugins/test-one', 0777, true)) {
throw new \RuntimeException('Unable to create test directory for plugin test-one');
}
if (!file_put_contents(
$projectDir . '/wp-content/plugins/test-one/plugin.php',
<<< PHP
<?php
/**
* Plugin Name: Test One
*/
function test_one_loaded(){}
PHP
)) {
throw new \RuntimeException('Unable to create test plugin file for plugin test-one');
Expand All @@ -89,9 +164,16 @@ function test_one_loaded(){}
<?php
/**
* Plugin Name: Test Two
* Description: During activation this plugin will clear the `active_plugins` option for reasons.
*/
function test_two_loaded(){}
function test_two_loaded(){ }
function test_two_activated(){
update_option('active_plugins', []);
}
register_activation_hook(__FILE__, 'test_two_activated');
PHP
)) {
throw new \RuntimeException('Unable to create test plugin file for plugin test-two');
Expand All @@ -117,6 +199,15 @@ static function () use ($wpLoader, $projectDir) {

Assert::assertTrue(function_exists('test_one_loaded'));
Assert::assertTrue(function_exists('test_two_loaded'));
Assert::assertEquals(
['test-one/plugin.php','test-two/plugin.php'],
get_option('active_plugins')
);
global $wpdb;
Assert::assertEquals(
serialize(['test-one/plugin.php','test-two/plugin.php']),
$wpdb->get_var("select option_value from {$wpdb->prefix}options where option_name = 'active_plugins'")
);
}
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ public function test_something():void{
public function should_not_be_strict_about_wpdb_connection_id_in_sq_lite_database(): void
{
$wpRootDir = FS::tmpDir('wploader_');
$db = new SQLiteDatabase($wpRootDir, 'db.sqlite', 'wp_');
$db = new SQLiteDatabase($wpRootDir, 'db.sqlite', 'wptests_');
Installation::scaffold($wpRootDir);
$db->create();
$testcaseFile = $wpRootDir . '/BreakingTest.php';
Expand Down

0 comments on commit de3f631

Please sign in to comment.