Commit fbd2868ef30 for woocommerce

commit fbd2868ef30bf5f711e3c5b3627b724826b6bdf2
Author: Kamal Hosen <kamalhosen8920@gmail.com>
Date:   Wed Jul 22 18:07:42 2026 +0600

    Fix TypeError when screen ID is not a string in visual attribute script enqueue (#66655)

    * Guard against non-string screen ID in visual attribute script enqueue
    * Add changelog entry for visual attribute screen ID fix

diff --git a/plugins/woocommerce/changelog/fix-66528-strpos-typeerror-visual-attribute-admin b/plugins/woocommerce/changelog/fix-66528-strpos-typeerror-visual-attribute-admin
new file mode 100644
index 00000000000..0a0949c1c82
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-66528-strpos-typeerror-visual-attribute-admin
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Guard against non-string screen ID in visual attribute script enqueue
diff --git a/plugins/woocommerce/src/Internal/ProductAttributes/VisualAttributeTermAdmin.php b/plugins/woocommerce/src/Internal/ProductAttributes/VisualAttributeTermAdmin.php
index 60ed1f25859..b1017c5a585 100644
--- a/plugins/woocommerce/src/Internal/ProductAttributes/VisualAttributeTermAdmin.php
+++ b/plugins/woocommerce/src/Internal/ProductAttributes/VisualAttributeTermAdmin.php
@@ -314,7 +314,7 @@ class VisualAttributeTermAdmin implements RegisterHooksInterface {
 	public function enqueue_visual_attribute_script(): void {
 		$screen = get_current_screen();

-		if ( ! $screen ) {
+		if ( ! $screen || ! is_string( $screen->id ) ) {
 			return;
 		}

diff --git a/plugins/woocommerce/tests/php/src/Internal/ProductAttributes/VisualAttributeTermAdminTest.php b/plugins/woocommerce/tests/php/src/Internal/ProductAttributes/VisualAttributeTermAdminTest.php
index 35dfd5b0d7c..c62e4977dfd 100644
--- a/plugins/woocommerce/tests/php/src/Internal/ProductAttributes/VisualAttributeTermAdminTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/ProductAttributes/VisualAttributeTermAdminTest.php
@@ -10,6 +10,7 @@ declare( strict_types = 1 );
 namespace Automattic\WooCommerce\Tests\Internal\ProductAttributes;

 use Automattic\WooCommerce\Internal\ProductAttributes\VisualAttributeTermAdmin;
+use Automattic\WooCommerce\Internal\ProductAttributes\VisualAttributeTermMeta;
 use WC_Unit_Test_Case;

 /**
@@ -234,4 +235,46 @@ class VisualAttributeTermAdminTest extends WC_Unit_Test_Case {
 			wc_delete_attribute( $attribute_id );
 		}
 	}
+
+	/**
+	 * @testdox Should not throw a TypeError when the current screen has a non-string id.
+	 *
+	 * Reproduces issue #66528: Visual Composer calls do_action('admin_enqueue_scripts', NULL),
+	 * which triggers enqueue_visual_attribute_script() in a context where get_current_screen()
+	 * may return a screen object whose id is an integer (post ID) rather than a string,
+	 * causing strpos(): Argument #1 ($haystack) must be of type string.
+	 */
+	public function test_does_not_fatal_on_non_string_screen_id(): void {
+		// We need the wc-visual attribute type available, same setup as other tests.
+		switch_theme( 'twentytwentyfour' );
+		delete_option( 'woocommerce_feature_wc_visual_attribute_enabled' );
+		wc_get_container()
+			->get( \Automattic\WooCommerce\Internal\Features\FeaturesController::class )
+			->change_feature_enable( 'wc-visual-attribute', true );
+
+		$instance = wc_get_container()->get( VisualAttributeTermAdmin::class );
+
+		// Simulate the scenario where get_current_screen() returns a screen with an integer id
+		// (e.g. a post ID), as happens when third-party code triggers admin_enqueue_scripts
+		// from outside the normal admin context.
+		$screen = \WP_Screen::get( 'test-screen' );
+		// Non-string, integer id like in the reported error.
+		$screen->id = 35202; // phpcs:ignore Generic.Formatting.MultipleStatementAlignment.IncorrectWarning
+
+		$original_screen           = isset( $GLOBALS['current_screen'] ) ? $GLOBALS['current_screen'] : null;
+		$GLOBALS['current_screen'] = $screen; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
+
+		try {
+			// This should not throw a TypeError even though $screen->id is an integer.
+			$instance->enqueue_visual_attribute_script();
+			// If we reach here, the method handled the non-string id gracefully.
+			$this->assertTrue( true );
+		} catch ( \TypeError $e ) {
+			$this->fail( 'TypeError thrown: ' . $e->getMessage() );
+		} finally {
+			$GLOBALS['current_screen'] = $original_screen; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
+			delete_option( 'woocommerce_feature_wc_visual_attribute_enabled' );
+			switch_theme( $this->original_theme );
+		}
+	}
 }