Commit a8be23289e6 for woocommerce

commit a8be23289e60780d7b58931384c3bedc303418cb
Author: agent-sandbox-woocommerce[bot] <282076412+agent-sandbox-woocommerce[bot]@users.noreply.github.com>
Date:   Mon Jun 8 08:55:39 2026 -0400

    Fix fatal TypeError in wc_modify_map_meta_cap() on PHP 8+ for invalid user IDs (#65506)

    * Fix fatal TypeError in wc_modify_map_meta_cap() on PHP 8+

    On PHP 8+, property_exists() throws a TypeError when its first argument
    is not an object or string. get_userdata() returns false for invalid
    user IDs (e.g. 0, deleted users), causing a fatal crash when
    current_user_can() is called with a user-modification capability
    (edit_user, remove_user, promote_user, delete_user) and a non-existent
    user ID—reliably triggered by Yoast SEO's First-Time Configuration
    wizard for shop_manager users when site is configured as Organization.

    Guard the property_exists() call by checking that get_userdata() returns
    a WP_User instance before proceeding; break out of the switch case
    otherwise, leaving $caps unchanged.

    Fixes: https://linear.app/a8c/issue/WOOPLUG-6719

    Triggered-By: michael.pretty

    * Remove stale PHPStan baseline entry and strengthen invalid-user test

    Drop the suppressed property_exists argument.type error from phpstan-baseline.neon
    now that the instanceof WP_User guard in wc_modify_map_meta_cap() resolves the
    underlying type issue. Also convert the invalid-user-id test to a @dataProvider
    covering both 0 and a stale non-zero id, and tighten the assertion to
    assertEquals( array( 'edit_users' ), $caps ) to pin the actual contract.

    Co-authored-by: prettyboymp

    ---------

    Co-authored-by: matticbot <matticbot@users.noreply.github.com>

diff --git a/plugins/woocommerce/changelog/fix-wooplug-6719-property-exists-false-php8 b/plugins/woocommerce/changelog/fix-wooplug-6719-property-exists-false-php8
new file mode 100644
index 00000000000..d13ff0acc99
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-wooplug-6719-property-exists-false-php8
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Fix fatal TypeError in wc_modify_map_meta_cap() on PHP 8+ when get_userdata() returns false for an invalid user ID.
diff --git a/plugins/woocommerce/includes/wc-user-functions.php b/plugins/woocommerce/includes/wc-user-functions.php
index f4c28eb9392..544271723bb 100644
--- a/plugins/woocommerce/includes/wc-user-functions.php
+++ b/plugins/woocommerce/includes/wc-user-functions.php
@@ -737,9 +737,12 @@ function wc_modify_map_meta_cap( $caps, $cap, $user_id, $args ) {
 					$caps[] = 'do_not_allow';
 				} elseif ( wc_current_user_has_role( 'shop_manager' ) ) {
 					// Shop managers can only edit customer info.
-					$userdata                    = get_userdata( $args[0] );
+					$userdata = get_userdata( $args[0] );
+					if ( ! $userdata instanceof WP_User ) {
+						break;
+					}
 					$shop_manager_editable_roles = apply_filters( 'woocommerce_shop_manager_editable_roles', array( 'customer' ) ); // phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment
-					if ( property_exists( $userdata, 'roles' ) && ! empty( $userdata->roles ) && ! array_intersect( $userdata->roles, $shop_manager_editable_roles ) ) {
+					if ( ! empty( $userdata->roles ) && ! array_intersect( $userdata->roles, $shop_manager_editable_roles ) ) {
 						$caps[] = 'do_not_allow';
 					}
 				}
diff --git a/plugins/woocommerce/phpstan-baseline.neon b/plugins/woocommerce/phpstan-baseline.neon
index d24e26ec5cf..e1f6d821e43 100644
--- a/plugins/woocommerce/phpstan-baseline.neon
+++ b/plugins/woocommerce/phpstan-baseline.neon
@@ -36525,12 +36525,6 @@ parameters:
 			count: 1
 			path: includes/wc-user-functions.php

-		-
-			message: '#^Parameter \#1 \$object_or_class of function property_exists expects object\|string, WP_User\|false given\.$#'
-			identifier: argument.type
-			count: 1
-			path: includes/wc-user-functions.php
-
 		-
 			message: '#^Parameter \#1 \$user of function user_can expects int\|WP_User, WP_User\|false given\.$#'
 			identifier: argument.type
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/util/class-wc-tests-user-functions.php b/plugins/woocommerce/tests/legacy/unit-tests/util/class-wc-tests-user-functions.php
index f8f3d6cca0e..8d4f6a755a1 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/util/class-wc-tests-user-functions.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/util/class-wc-tests-user-functions.php
@@ -129,6 +129,50 @@ class WC_Tests_User_Functions extends WC_Unit_Test_Case {
 		$this->assertEquals( array( 'edit_users' ), $caps );
 	}

+	/**
+	 * Data provider for test_wc_modify_map_meta_cap_invalid_user_id.
+	 *
+	 * @return array[]
+	 */
+	public function invalid_user_id_provider() {
+		return array(
+			'zero id'        => array( 0 ),
+			'stale non-zero' => array( 999999 ),
+		);
+	}
+
+	/**
+	 * Test that wc_modify_map_meta_cap does not fatal when $args[0] is not a valid user ID.
+	 *
+	 * On PHP 8+, property_exists() throws a TypeError when passed false (the return value
+	 * of get_userdata() for a missing user). This test ensures no fatal occurs and that
+	 * $caps is returned unchanged when the target user ID is invalid (e.g. 0 or a stale id).
+	 *
+	 * @dataProvider invalid_user_id_provider
+	 * @see https://github.com/woocommerce/woocommerce/issues/65171
+	 *
+	 * @param int $invalid_id A user ID that does not correspond to an existing user.
+	 */
+	public function test_wc_modify_map_meta_cap_invalid_user_id( $invalid_id ) {
+		$password = wp_generate_password();
+
+		$manager_id = wp_insert_user(
+			array(
+				'user_login' => 'test_manager_invalid',
+				'user_pass'  => $password,
+				'user_email' => 'manager_invalid@example.com',
+				'role'       => 'shop_manager',
+			)
+		);
+
+		wp_set_current_user( $manager_id );
+
+		// Passing an invalid user ID should not throw a TypeError on PHP 8+.
+		// The caps array must be returned unchanged — exactly the WordPress default.
+		$caps = map_meta_cap( 'edit_user', $manager_id, $invalid_id );
+		$this->assertEquals( array( 'edit_users' ), $caps );
+	}
+
 	/**
 	 * Test wc_shop_manager_has_capability function.
 	 *