diff --git a/src/wp-includes/abilities-api/class-wp-abilities-registry.php b/src/wp-includes/abilities-api/class-wp-abilities-registry.php index ecd6dc2785e70..02fedb8865d17 100644 --- a/src/wp-includes/abilities-api/class-wp-abilities-registry.php +++ b/src/wp-includes/abilities-api/class-wp-abilities-registry.php @@ -44,8 +44,8 @@ final class WP_Abilities_Registry { * @see wp_register_ability() * * @param string $name The name of the ability. The name must be a string containing a namespace - * prefix, i.e. `my-plugin/my-ability`. It can only contain lowercase - * alphanumeric characters, dashes and the forward slash. + * prefix, i.e. `my-plugin/my-ability` or `my-plugin/v1/my-ability`. It can + * only contain lowercase alphanumeric characters, dashes and the forward slash. * @param array $args { * An associative array of arguments for the ability. * @@ -78,11 +78,11 @@ final class WP_Abilities_Registry { * @return WP_Ability|null The registered ability instance on success, null on failure. */ public function register( string $name, array $args ): ?WP_Ability { - if ( ! preg_match( '/^[a-z0-9-]+\/[a-z0-9-]+$/', $name ) ) { + if ( ! preg_match( '/^[a-z0-9-]+\/([a-z0-9-]+\/)?[a-z0-9-]+$/', $name ) ) { _doing_it_wrong( __METHOD__, __( - 'Ability name must be a string containing a namespace prefix, i.e. "my-plugin/my-ability". It can only contain lowercase alphanumeric characters, dashes and the forward slash.' + 'Ability name must be a string containing a namespace prefix, i.e. "my-plugin/my-ability" or "my-plugin/v1/my-ability". It can only contain lowercase alphanumeric characters, dashes and the forward slash.' ), '6.9.0' ); diff --git a/tests/phpunit/tests/abilities-api/wpAbilitiesRegistry.php b/tests/phpunit/tests/abilities-api/wpAbilitiesRegistry.php index badd81c3b626a..a6b1b1ec4c0c8 100644 --- a/tests/phpunit/tests/abilities-api/wpAbilitiesRegistry.php +++ b/tests/phpunit/tests/abilities-api/wpAbilitiesRegistry.php @@ -134,6 +134,20 @@ public function test_register_invalid_uppercase_characters_in_name() { $this->assertNull( $result ); } + /** + * Should reject ability name with more than two slashes. + * + * @ticket 64098 + * + * @covers WP_Abilities_Registry::register + * + * @expectedIncorrectUsage WP_Abilities_Registry::register + */ + public function test_register_invalid_too_many_slashes_in_name() { + $result = $this->registry->register( 'test/v1/extra/add-numbers', self::$test_ability_args ); + $this->assertNull( $result ); + } + /** * Should reject ability registration without a label. * @@ -405,10 +419,23 @@ public function test_register_incorrect_already_registered_ability() { public function test_register_new_ability() { $result = $this->registry->register( self::$test_ability_name, self::$test_ability_args ); - $this->assertEquals( - new WP_Ability( self::$test_ability_name, self::$test_ability_args ), - $result - ); + $this->assertInstanceOf( WP_Ability::class, $result ); + $this->assertSame( self::$test_ability_name, $result->get_name() ); + } + + /** + * Should successfully register a new ability with a versioned name. + * + * @ticket 64098 + * + * @covers WP_Abilities_Registry::register + */ + public function test_register_new_ability_with_versioned_name() { + $versioned_name = 'test/v1/add-numbers'; + $result = $this->registry->register( $versioned_name, self::$test_ability_args ); + + $this->assertInstanceOf( WP_Ability::class, $result ); + $this->assertSame( $versioned_name, $result->get_name() ); } /** @@ -468,7 +495,7 @@ public function test_get_registered_for_known_ability() { $this->registry->register( 'test/three', self::$test_ability_args ); $result = $this->registry->get_registered( 'test/two' ); - $this->assertEquals( 'test/two', $result->get_name() ); + $this->assertSame( 'test/two', $result->get_name() ); } /** @@ -499,7 +526,7 @@ public function test_unregister_for_known_ability() { $this->registry->register( 'test/three', self::$test_ability_args ); $result = $this->registry->unregister( 'test/three' ); - $this->assertEquals( 'test/three', $result->get_name() ); + $this->assertSame( 'test/three', $result->get_name() ); $this->assertFalse( $this->registry->is_registered( 'test/three' ) ); }