Commit 1d0d103e1dc for woocommerce

commit 1d0d103e1dcfe23dd4a39b1f578220a2c134106e
Author: Jorge A. Torres <jorge.torres@automattic.com>
Date:   Thu May 14 21:44:04 2026 +0100

    Fix PHPCS error on PHP 8.5 by switching PSR-4 sniff provider (#64875)

diff --git a/.ai/skills/woocommerce-dev-cycle/php-linting-patterns.md b/.ai/skills/woocommerce-dev-cycle/php-linting-patterns.md
index bd12395d6e3..94e3f439e87 100644
--- a/.ai/skills/woocommerce-dev-cycle/php-linting-patterns.md
+++ b/.ai/skills/woocommerce-dev-cycle/php-linting-patterns.md
@@ -39,7 +39,7 @@ pnpm lint:php:fix
 ### Quick Reference Table

 | Issue | Wrong | Correct |
-|-------|-------|---------|
+| ----- | ----- | ------- |
 | **Translators comment** | Before return | Before function call |
 | **File docblock (PSR-12)** | After `declare()` | Before `declare()` |
 | **Indentation** | Spaces | Tabs only |
@@ -121,7 +121,7 @@ if ( ! class_exists( 'WC_Payments_Utils' ) ) {
      * Mock class for testing.
      *
      * phpcs:disable Squiz.Classes.ClassFileName.NoMatch
-     * phpcs:disable Suin.Classes.PSR4.IncorrectClassName
+     * phpcs:disable SlevomatCodingStandard.Files.TypeNameMatchesFileName.NoMatchBetweenTypeNameAndFileName
      * phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
      */
     class WC_Payments_Utils {
diff --git a/plugins/woocommerce/bin/composer/phpcs/composer.json b/plugins/woocommerce/bin/composer/phpcs/composer.json
index 5cd171ae292..a3af37aabb4 100644
--- a/plugins/woocommerce/bin/composer/phpcs/composer.json
+++ b/plugins/woocommerce/bin/composer/phpcs/composer.json
@@ -3,7 +3,7 @@
 		"woocommerce/woocommerce-sniffs": "1.0.0",
 		"phpcompatibility/php-compatibility": "dev-develop#9013cd039fe5740953f9fdeebd19d901b80e26f2 as 9.3.10",
 		"sirbrillig/phpcs-changed": "^2.11.1",
-		"suin/phpcs-psr4-sniff": "^3.0"
+		"slevomat/coding-standard": "^6.3"
 	},
 	"config": {
 		"platform": {
diff --git a/plugins/woocommerce/bin/composer/phpcs/composer.lock b/plugins/woocommerce/bin/composer/phpcs/composer.lock
index 3d99d4bd365..a5d9f2ea007 100644
--- a/plugins/woocommerce/bin/composer/phpcs/composer.lock
+++ b/plugins/woocommerce/bin/composer/phpcs/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "4b7c50b51b5a09878954339be989bfdd",
+    "content-hash": "3b518363dc38fa21955eb79c65519597",
     "packages": [],
     "packages-dev": [
         {
@@ -770,61 +770,6 @@
             ],
             "time": "2025-11-04T16:30:35+00:00"
         },
-        {
-            "name": "suin/phpcs-psr4-sniff",
-            "version": "v3.0.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/suin/phpcs-psr4-sniff.git",
-                "reference": "b000ca1e3d04c9876b39c2e56859760b93dfc84d"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/suin/phpcs-psr4-sniff/zipball/b000ca1e3d04c9876b39c2e56859760b93dfc84d",
-                "reference": "b000ca1e3d04c9876b39c2e56859760b93dfc84d",
-                "shasum": ""
-            },
-            "require": {
-                "ext-json": "*",
-                "php": ">=7.1",
-                "slevomat/coding-standard": ">=4.7 <8.0.0",
-                "squizlabs/php_codesniffer": ">=3.3 <4.0.0"
-            },
-            "type": "phpcodesniffer-standard",
-            "autoload": {
-                "psr-0": {
-                    "Suin\\Sniffs\\Classes\\": "src"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "suin",
-                    "email": "suinyeze@gmail.com",
-                    "homepage": "https://github.com/suin",
-                    "role": "Developer"
-                }
-            ],
-            "description": "PHP_CodeSniffer sniff that checks class name matches PSR-4 project structure.",
-            "homepage": "https://github.com/suin/php",
-            "keywords": [
-                "PSR-4",
-                "coding-standards",
-                "coding-style",
-                "namespace",
-                "php-codesniffer",
-                "phpcs",
-                "static-analysis"
-            ],
-            "support": {
-                "issues": "https://github.com/suin/php/issues",
-                "source": "https://github.com/suin/phpcs-psr4-sniff/tree/v3.0.0"
-            },
-            "time": "2021-06-02T06:16:24+00:00"
-        },
         {
             "name": "woocommerce/woocommerce-sniffs",
             "version": "1.0.0",
@@ -950,5 +895,5 @@
     "platform-overrides": {
         "php": "7.4"
     },
-    "plugin-api-version": "2.9.0"
+    "plugin-api-version": "2.6.0"
 }
diff --git a/plugins/woocommerce/changelog/fix-phpcs-suin-php-8-5 b/plugins/woocommerce/changelog/fix-phpcs-suin-php-8-5
new file mode 100644
index 00000000000..55aa3c0c528
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-phpcs-suin-php-8-5
@@ -0,0 +1,4 @@
+Significance: patch
+Type: dev
+
+Dev: swap unmaintained Suin PSR-4 sniff for Slevomat to keep PHPCS working on PHP 8.5.
diff --git a/plugins/woocommerce/phpcs.xml b/plugins/woocommerce/phpcs.xml
index 4de14ca7520..690df2cbe74 100644
--- a/plugins/woocommerce/phpcs.xml
+++ b/plugins/woocommerce/phpcs.xml
@@ -101,14 +101,17 @@
 		<exclude-pattern>src/Internal/Api/</exclude-pattern>
 	</rule>

-	<rule ref="Suin.Classes.PSR4">
+	<rule ref="SlevomatCodingStandard.Files.TypeNameMatchesFileName">
 		<include-pattern>src/</include-pattern>
 		<include-pattern>tests/php/src/</include-pattern>
 		<exclude-pattern>plugins/woocommerce/src/Admin/Notes/DeprecatedNotes.php</exclude-pattern>
 		<exclude-pattern>plugins/woocommerce/tests/php/src/Proxies/ExampleClasses/</exclude-pattern>
 		<exclude-pattern>plugins/woocommerce/tests/php/src/Internal/DependencyManagement/ExampleClasses/</exclude-pattern>
 		<properties>
-			<property name="composerJsonPath" value="composer.json"/>
+			<property name="rootNamespaces" type="array">
+				<element key="src" value="Automattic\WooCommerce"/>
+				<element key="tests/php/src" value="Automattic\WooCommerce\Tests"/>
+			</property>
 		</properties>
 	</rule>

diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/features/payment-gateway-suggestions/evaluate-suggestion.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/features/payment-gateway-suggestions/evaluate-suggestion.php
index 3b0a70952c6..a0a50ac1cb7 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/features/payment-gateway-suggestions/evaluate-suggestion.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/features/payment-gateway-suggestions/evaluate-suggestion.php
@@ -385,7 +385,7 @@ class WC_Admin_Tests_PaymentGatewaySuggestions_EvaluateSuggestion extends WC_Uni
 	}
 }

-//phpcs:disable Generic.Files.OneObjectStructurePerFile.MultipleFound, Squiz.Classes.ClassFileName.NoMatch, Suin.Classes.PSR4.IncorrectClassName
+//phpcs:disable Generic.Files.OneObjectStructurePerFile.MultipleFound, Squiz.Classes.ClassFileName.NoMatch, SlevomatCodingStandard.Files.TypeNameMatchesFileName.NoMatchBetweenTypeNameAndFileName
 /**
  * TestableEvaluateSuggestion class.
  */
@@ -399,4 +399,4 @@ class TestableEvaluateSuggestion extends EvaluateSuggestion {
 		return self::$memo;
 	}
 }
-//phpcs:enable Generic.Files.OneObjectStructurePerFile.MultipleFound, Squiz.Classes.ClassFileName.NoMatch, Suin.Classes.PSR4.IncorrectClassName
+//phpcs:enable Generic.Files.OneObjectStructurePerFile.MultipleFound, Squiz.Classes.ClassFileName.NoMatch, SlevomatCodingStandard.Files.TypeNameMatchesFileName.NoMatchBetweenTypeNameAndFileName
diff --git a/plugins/woocommerce/tests/php/src/Blocks/StoreApi/Routes/CheckoutSessionsComplete.php b/plugins/woocommerce/tests/php/src/Blocks/StoreApi/Routes/CheckoutSessionsComplete.php
index dea405c4b8a..9b691f32181 100644
--- a/plugins/woocommerce/tests/php/src/Blocks/StoreApi/Routes/CheckoutSessionsComplete.php
+++ b/plugins/woocommerce/tests/php/src/Blocks/StoreApi/Routes/CheckoutSessionsComplete.php
@@ -845,7 +845,7 @@ class CheckoutSessionsComplete extends ControllerTestCase {
 	}
 }

-// phpcs:disable Generic.Files.OneObjectStructurePerFile.MultipleFound, Squiz.Classes.ClassFileName.NoMatch, Suin.Classes.PSR4.IncorrectClassName
+// phpcs:disable Generic.Files.OneObjectStructurePerFile.MultipleFound, Squiz.Classes.ClassFileName.NoMatch, SlevomatCodingStandard.Files.TypeNameMatchesFileName.NoMatchBetweenTypeNameAndFileName

 /**
  * Mock Agentic Payment Gateway for testing.
diff --git a/plugins/woocommerce/tests/php/src/CLAUDE.md b/plugins/woocommerce/tests/php/src/CLAUDE.md
index c0d7511280e..54ecaab0333 100644
--- a/plugins/woocommerce/tests/php/src/CLAUDE.md
+++ b/plugins/woocommerce/tests/php/src/CLAUDE.md
@@ -8,7 +8,7 @@
 ### Rule: Use targeted assertions, not full equality checks

 | Pattern | Brittle (Wrong) | Resilient (Correct) |
-|---------|-----------------|---------------------|
+| ------- | --------------- | ------------------- |
 | Array key + value | `assertSame(['key' => null], $arr)` | `assertArrayHasKey('key', $arr)` + `assertNull($arr['key'])` |
 | Single value | `assertSame(['a' => 1, 'b' => 2], $r)` | `assertArrayHasKey('a', $r)` + `assertSame(1, $r['a'])` |
 | Nested | `assertSame(['m' => ['e' => null]], $r)` | `assertArrayHasKey('e', $r['m'])` + `assertNull($r['m']['e'])` |
@@ -31,7 +31,7 @@ $this->assertNull( $result['messages']['not_supported'] );
 **Priority order**: Most specific → Structure → General

 | Assertion | Use | Example |
-|-----------|-----|---------|
+| --------- | --- | ------- |
 | `assertSame()` | Strict === | `assertSame(5, $count)` |
 | `assertEquals()` | Loose == | `assertEquals('5', $count)` |
 | `assertNull()` | Null check | `assertNull($error)` |
@@ -50,7 +50,7 @@ if ( ! class_exists( 'WC_Payments_Utils' ) ) {
      * Mock for testing.
      *
      * phpcs:disable Squiz.Classes.ClassFileName.NoMatch
-     * phpcs:disable Suin.Classes.PSR4.IncorrectClassName
+     * phpcs:disable SlevomatCodingStandard.Files.TypeNameMatchesFileName.NoMatchBetweenTypeNameAndFileName
      * phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
      */
     class WC_Payments_Utils {
@@ -65,7 +65,7 @@ if ( ! class_exists( 'WC_Payments_Utils' ) ) {
 **Why ignores needed:**

 - `ClassFileName.NoMatch` - Mock doesn't match file name
-- `PSR4.IncorrectClassName` - External class not PSR-4
+- `TypeNameMatchesFileName.NoMatchBetweenTypeNameAndFileName` - External class not PSR-4
 - `ValidClassName.NotCamelCaps` - Uses underscores

 ## Unused Closure Parameters
@@ -226,7 +226,7 @@ pnpm test:php:env -- --testdox --filter WooPaymentsServiceTest
 **Common issues:**

 | Error | Cause | Fix |
-|-------|-------|-----|
+| ----- | ----- | --- |
 | `Undefined array key` | Missing key | Check code returns key |
 | `Arrays not identical` | Extra/missing keys | Use targeted assertions |
 | `Mock not called` | Code path skipped | Check test setup |
diff --git a/plugins/woocommerce/tests/php/src/Internal/Logging/RemoteLoggerTest.php b/plugins/woocommerce/tests/php/src/Internal/Logging/RemoteLoggerTest.php
index a247fe6ae8e..46eed93d380 100644
--- a/plugins/woocommerce/tests/php/src/Internal/Logging/RemoteLoggerTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/Logging/RemoteLoggerTest.php
@@ -720,7 +720,7 @@ namespace Automattic\WooCommerce\Tests\Internal\Logging {
 	}


-//phpcs:disable Generic.Files.OneObjectStructurePerFile.MultipleFound, Squiz.Classes.ClassFileName.NoMatch, Suin.Classes.PSR4.IncorrectClassName
+//phpcs:disable Generic.Files.OneObjectStructurePerFile.MultipleFound, Squiz.Classes.ClassFileName.NoMatch, SlevomatCodingStandard.Files.TypeNameMatchesFileName.NoMatchBetweenTypeNameAndFileName
 	/**
 	 * Mock class that extends RemoteLogger to allow overriding is_dev_or_local_environment.
 	 */
@@ -748,7 +748,7 @@ namespace Automattic\WooCommerce\Tests\Internal\Logging {
 			return $this->is_dev_or_local;
 		}
 	}
-//phpcs:enable Generic.Files.OneObjectStructurePerFile.MultipleFound, Squiz.Classes.ClassFileName.NoMatch, Suin.Classes.PSR4.IncorrectClassName
+//phpcs:enable Generic.Files.OneObjectStructurePerFile.MultipleFound, Squiz.Classes.ClassFileName.NoMatch, SlevomatCodingStandard.Files.TypeNameMatchesFileName.NoMatchBetweenTypeNameAndFileName
 }

 /**
diff --git a/plugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Orders/UpdateUtilsTest.php b/plugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Orders/UpdateUtilsTest.php
index 881aaf99cc2..cf0879aa0ee 100644
--- a/plugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Orders/UpdateUtilsTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/RestApi/Routes/V4/Orders/UpdateUtilsTest.php
@@ -75,7 +75,7 @@ class UpdateUtilsTest extends WC_Unit_Test_Case {
  *
  * phpcs:disable Generic.Files.OneObjectStructurePerFile.MultipleFound
  * phpcs:disable Squiz.Classes.ClassFileName.NoMatch
- * phpcs:disable Suin.Classes.PSR4.IncorrectClassName
+ * phpcs:disable SlevomatCodingStandard.Files.TypeNameMatchesFileName.NoMatchBetweenTypeNameAndFileName
  */
 class TestableUpdateUtils extends UpdateUtils {