From e361dddff79676330fcf9600c5b9b91d31b72d66 Mon Sep 17 00:00:00 2001 From: Geoff Taylor Date: Thu, 2 Apr 2026 18:59:48 -0400 Subject: [PATCH] fix: make name optional in updateProduct mutation (#1014) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: make name optional in updateProduct mutation The UpdateProductInput inherited name as non_null from CreateProductInput, requiring callers to always provide a name even when only updating other fields. Now name is optional for updates — the existing name is preserved when not provided. * chore: Linter compliances met --- includes/mutation/class-product-update.php | 12 ++++-- tests/wpunit/ProductMutationsTest.php | 40 ++++++++++++++++++++ vendor-prefixed/firebase/php-jwt/src/JWK.php | 8 ++++ 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/includes/mutation/class-product-update.php b/includes/mutation/class-product-update.php index 76e7b018..16637064 100644 --- a/includes/mutation/class-product-update.php +++ b/includes/mutation/class-product-update.php @@ -39,15 +39,21 @@ class Product_Update { */ public static function get_input_fields() { return array_merge( + Product_Create::get_input_fields(), [ - 'id' => [ + 'id' => [ 'type' => [ 'non_null' => 'ID' ], 'description' => static function () { return __( 'Unique identifier for the product.', 'wp-graphql-woocommerce' ); }, ], - ], - Product_Create::get_input_fields() + 'name' => [ + 'type' => 'String', + 'description' => static function () { + return __( 'Name of the product.', 'wp-graphql-woocommerce' ); + }, + ], + ] ); } diff --git a/tests/wpunit/ProductMutationsTest.php b/tests/wpunit/ProductMutationsTest.php index 59dbd4b2..16ea3425 100644 --- a/tests/wpunit/ProductMutationsTest.php +++ b/tests/wpunit/ProductMutationsTest.php @@ -832,4 +832,44 @@ class ProductMutationsTest extends \Tests\WPGraphQL\WooCommerce\TestCase\WooGrap $product = wc_get_product( $product_id ); $this->assertFalse( $product ); } + + public function testUpdateProductWithoutName() { + $product_id = $this->factory->product->createSimple( + [ + 'name' => 'Original Name', + 'regular_price' => 10, + ] + ); + + $query = ' + mutation ( $input: UpdateProductInput! ) { + updateProduct(input: $input) { + product { + databaseId + name + ... on ProductWithPricing { + regularPrice(format: RAW) + } + } + } + } + '; + + $variables = [ + 'input' => [ + 'id' => $product_id, + 'regularPrice' => 25.00, + ], + ]; + + $this->loginAsShopManager(); + $response = $this->graphql( compact( 'query', 'variables' ) ); + $expected = [ + $this->expectedField( 'updateProduct.product.databaseId', $product_id ), + $this->expectedField( 'updateProduct.product.name', 'Original Name' ), + $this->expectedField( 'updateProduct.product.regularPrice', '25' ), + ]; + + $this->assertQuerySuccessful( $response, $expected ); + } } \ No newline at end of file diff --git a/vendor-prefixed/firebase/php-jwt/src/JWK.php b/vendor-prefixed/firebase/php-jwt/src/JWK.php index 3427a8c3..6331ab38 100644 --- a/vendor-prefixed/firebase/php-jwt/src/JWK.php +++ b/vendor-prefixed/firebase/php-jwt/src/JWK.php @@ -246,6 +246,14 @@ class JWK ): string { $mod = JWT::urlsafeB64Decode($n); $exp = JWT::urlsafeB64Decode($e); + // Correct encoding for ASN1, as ints are represented as unsigned in jwk + // but signed in ASN1. Prepending null byte makes it unsigned. + if (\strlen($mod) > 0 && \ord($mod[0]) >= 128) { + $mod = \chr(0) . $mod; + } + if (\strlen($exp) > 0 && \ord($exp[0]) >= 128) { + $exp = \chr(0) . $exp; + } $modulus = \pack('Ca*a*', 2, self::encodeLength(\strlen($mod)), $mod); $publicExponent = \pack('Ca*a*', 2, self::encodeLength(\strlen($exp)), $exp);