Commit 8135836449 for woocommerce
commit 8135836449bec5169e1b3272b1365a61bfa591d2
Author: Chi-Hsuan Huang <chihsuan.tw@gmail.com>
Date: Fri Apr 25 17:45:17 2025 +0800
[Blueprint] Add restrictions for options in Blueprint importer (#57381)
* Implement restricted options handling in ImportSetSiteOptions
- Added a list of restricted WordPress options that cannot be modified for security reasons.
- Updated the process method to skip updates for these restricted options and log warnings accordingly.
- Enhanced unit tests to verify that restricted options are not modified and appropriate warnings are generated.
* Add changelog
* Change message
diff --git a/packages/php/blueprint/changelog/wooplug-3964-blueprint-protect-critical-options b/packages/php/blueprint/changelog/wooplug-3964-blueprint-protect-critical-options
new file mode 100644
index 0000000000..8554256dbd
--- /dev/null
+++ b/packages/php/blueprint/changelog/wooplug-3964-blueprint-protect-critical-options
@@ -0,0 +1,4 @@
+Significance: patch
+Type: enhancement
+
+Implement restricted options handling in ImportSetSiteOptions
diff --git a/packages/php/blueprint/src/Importers/ImportSetSiteOptions.php b/packages/php/blueprint/src/Importers/ImportSetSiteOptions.php
index 53cd70e791..7cda12f099 100644
--- a/packages/php/blueprint/src/Importers/ImportSetSiteOptions.php
+++ b/packages/php/blueprint/src/Importers/ImportSetSiteOptions.php
@@ -17,6 +17,28 @@ use Automattic\WooCommerce\Blueprint\UseWPFunctions;
class ImportSetSiteOptions implements StepProcessor {
use UseWPFunctions;
+ /**
+ * List of WordPress options that should not be modified.
+ *
+ * @var array<string>
+ */
+ private const RESTRICTED_OPTIONS = array(
+ 'siteurl',
+ 'home',
+ 'active_plugins',
+ 'template',
+ 'stylesheet',
+ 'admin_email',
+ 'unfiltered_html',
+ 'users_can_register',
+ 'default_role',
+ 'db_version',
+ 'cron',
+ 'rewrite_rules',
+ 'wp_user_roles',
+ );
+
+
/**
* Process the step.
*
@@ -27,16 +49,23 @@ class ImportSetSiteOptions implements StepProcessor {
public function process( $schema ): StepProcessorResult {
$result = StepProcessorResult::success( SetSiteOptions::get_step_name() );
foreach ( $schema->options as $key => $value ) {
+ // Skip if the option should not be modified.
+ if ( in_array( $key, self::RESTRICTED_OPTIONS, true ) ) {
+ $result->add_warn( "Cannot modify '{$key}' option: Modifying is restricted for this key." );
+ continue;
+ }
+
$value = json_decode( wp_json_encode( $value ), true );
$updated = $this->wp_update_option( $key, $value );
if ( $updated ) {
- $result->add_info( "{$key} has been updated" );
- } else {
- $current_value = $this->wp_get_option( $key );
- if ( $current_value === $value ) {
- $result->add_info( "{$key} has not been updated because the current value is already up to date." );
- }
+ $result->add_info( "{$key} has been updated." );
+ continue;
+ }
+
+ $current_value = $this->wp_get_option( $key );
+ if ( $current_value === $value ) {
+ $result->add_info( "{$key} has not been updated because the current value is already up to date." );
}
}
diff --git a/packages/php/blueprint/tests/Unit/Importers/ImportSetSiteOptionsTest.php b/packages/php/blueprint/tests/Unit/Importers/ImportSetSiteOptionsTest.php
index 8f6facda1b..3d2a1cdd87 100644
--- a/packages/php/blueprint/tests/Unit/Importers/ImportSetSiteOptionsTest.php
+++ b/packages/php/blueprint/tests/Unit/Importers/ImportSetSiteOptionsTest.php
@@ -32,8 +32,8 @@ class ImportSetSiteOptionsTest extends TestCase {
public function test_process_updates_options_successfully() {
$schema = Mockery::mock();
$schema->options = array(
- 'site_name' => 'My New Site',
- 'admin_email' => 'admin@example.com',
+ 'site_name' => 'My New Site',
+ 'woocommerce_default_country' => 'JP',
);
$import_set_site_options = Mockery::mock( ImportSetSiteOptions::class )
@@ -45,7 +45,7 @@ class ImportSetSiteOptionsTest extends TestCase {
->with( 'site_name', 'My New Site' )
->andReturn( true );
$import_set_site_options->shouldReceive( 'wp_update_option' )
- ->with( 'admin_email', 'admin@example.com' )
+ ->with( 'woocommerce_default_country', 'JP' )
->andReturn( true );
$result = $import_set_site_options->process( $schema );
@@ -55,8 +55,8 @@ class ImportSetSiteOptionsTest extends TestCase {
$messages = $result->get_messages( 'info' );
$this->assertCount( 2, $messages );
- $this->assertEquals( 'site_name has been updated', $messages[0]['message'] );
- $this->assertEquals( 'admin_email has been updated', $messages[1]['message'] );
+ $this->assertEquals( 'site_name has been updated.', $messages[0]['message'] );
+ $this->assertEquals( 'woocommerce_default_country has been updated.', $messages[1]['message'] );
}
/**
@@ -94,6 +94,34 @@ class ImportSetSiteOptionsTest extends TestCase {
$this->assertEquals( 'site_name has not been updated because the current value is already up to date.', $messages[0]['message'] );
}
+ /**
+ * Test when restricted options are attempted to be updated.
+ *
+ * @return void
+ */
+ public function test_process_restricted_options() {
+ $schema = Mockery::mock();
+ $schema->options = array(
+ 'admin_email' => 'danger@example.com',
+ 'active_plugins' => array( 'fake-plugin/fake-plugin.php' ),
+ );
+ $import_set_site_options = Mockery::mock( ImportSetSiteOptions::class )
+ ->makePartial()
+ ->shouldAllowMockingProtectedMethods();
+
+ $result = $import_set_site_options->process( $schema );
+
+ $this->assertInstanceOf( StepProcessorResult::class, $result );
+ $this->assertTrue( $result->is_success() );
+
+ $messages = $result->get_messages( 'warn' );
+ $this->assertCount( 2, $messages );
+ $this->assertEquals( "Cannot modify 'admin_email' option: Modifying is restricted for this key.", $messages[0]['message'] );
+ $this->assertEquals( "Cannot modify 'active_plugins' option: Modifying is restricted for this key.", $messages[1]['message'] );
+ $this->assertNotEquals( get_option( 'admin_email' ), 'danger@example.com' );
+ $this->assertNotEquals( get_option( 'active_plugins' ), array( 'fake-plugin/fake-plugin.php' ) );
+ }
+
/**
* Test getting the step class.
*