From cdbb5c0409b4dd324654cd2defc2bb55dc6fdf94 Mon Sep 17 00:00:00 2001 From: Marian <42134098+IanDelMar@users.noreply.github.com> Date: Tue, 10 Sep 2024 05:49:03 +0200 Subject: [PATCH 01/20] Add ValidTaxonomySlugSniff - Adds `AbstractValidSlugSniff`, which can serve as a base for sniffs that check a function parameter to ensure it is a valid slug. - Refactors `ValidPostTypeSlugSniff` to extend `AbstractValidSlugSniff`. - Introduces `ValidTaxonomySlugSniff`, which also extends `AbstractValidSlugSniff`. - Adds `WPReservedKeywordHelper` to centrally store reserved keywords. All classes inherit the public property `$exclude` from `AbstractFunctionRestrictionsSniff`. `WPReservedKeywordHelper::$terms` requires a "Last updated for WordPress x.x." --- .github/release-checklist.md | 3 +- WordPress-Extra/ruleset.xml | 3 + WordPress/AbstractValidSlugSniff.php | 276 ++++++++++++++++++ .../ValidTaxonomySlugStandard.xml | 121 ++++++++ WordPress/Helpers/WPReservedKeywordHelper.php | 187 ++++++++++++ .../ValidPostTypeSlugSniff.php | 220 +++----------- .../ValidTaxonomySlugSniff.php | 84 ++++++ .../ValidTaxonomySlugUnitTest.1.inc | 70 +++++ .../ValidTaxonomySlugUnitTest.2.inc | 19 ++ .../ValidTaxonomySlugUnitTest.php | 115 ++++++++ phpunit.xml.dist | 1 + 11 files changed, 916 insertions(+), 183 deletions(-) create mode 100644 WordPress/AbstractValidSlugSniff.php create mode 100644 WordPress/Docs/NamingConventions/ValidTaxonomySlugStandard.xml create mode 100644 WordPress/Helpers/WPReservedKeywordHelper.php create mode 100644 WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php create mode 100644 WordPress/Tests/NamingConventions/ValidTaxonomySlugUnitTest.1.inc create mode 100644 WordPress/Tests/NamingConventions/ValidTaxonomySlugUnitTest.2.inc create mode 100644 WordPress/Tests/NamingConventions/ValidTaxonomySlugUnitTest.php diff --git a/.github/release-checklist.md b/.github/release-checklist.md index 108bea3aa..89cfbd9e0 100644 --- a/.github/release-checklist.md +++ b/.github/release-checklist.md @@ -28,7 +28,8 @@ PR for tracking changes for the x.x.x release. Target release date: **DOW MONTH - [ ] `$pluggable_functions` in `WordPress.NamingConventions.PrefixAllGlobals` - PR #xxx - [ ] `$pluggable_classes` in `WordPress.NamingConventions.PrefixAllGlobals` - PR #xxx - [ ] `$target_functions` in `WordPress.Security.PluginMenuSlug` - PR #xxx - - [ ] `$reserved_names` in `WordPress.NamingConventions.ValidPostTypeSlug` - PR #xxx + - [ ] `$post_types` in `WPReservedKeywordHelper` - PR #xxx + - [ ] `$terms` in `WPReservedKeywordHelper` - PR #xxx - [ ] `$wp_time_constants` in `WordPress.WP.CronInterval` - PR #xxx - [ ] `$known_test_classes` in `IsUnitTestTrait` - PR #xxx - [ ] ...etc... diff --git a/WordPress-Extra/ruleset.xml b/WordPress-Extra/ruleset.xml index 53da8be01..9dcf94c08 100644 --- a/WordPress-Extra/ruleset.xml +++ b/WordPress-Extra/ruleset.xml @@ -132,6 +132,9 @@ + + + diff --git a/WordPress/AbstractValidSlugSniff.php b/WordPress/AbstractValidSlugSniff.php new file mode 100644 index 000000000..99665c5f6 --- /dev/null +++ b/WordPress/AbstractValidSlugSniff.php @@ -0,0 +1,276 @@ + Key is reserved name, value irrelevant. + */ + protected $reserved_names; + + /** + * All valid tokens for the slug parameter. + * + * Set in `register()`. + * + * @var array + */ + private $valid_tokens = array(); + + /** + * Constructor. + * + * @since 3.0.0 + */ + public function __construct() { + $this->target_functions = $this->get_target_functions(); + $this->slug_type = $this->get_slug_type(); + $this->slug_type_plural = $this->get_slug_type_plural(); + $this->valid_characters = $this->get_valid_characters(); + $this->max_length = $this->get_max_length(); + $this->reserved_names = $this->get_reserved_names(); + } + + /** + * Retrieve function and parameter(s) pairs this sniff is looking for. + * + * The parameter or an array of parameters keyed by target function. + * An array of names is supported to allow for functions for which the + * parameter names have undergone name changes over time. + * + * @return array> Function parameter(s) pairs. + */ + abstract protected function get_target_functions(); + + /** + * Retrieve the slug type. + * + * @return string The slug type. + */ + abstract protected function get_slug_type(); + + /** + * Retrieve the plural slug type. + * + * @return string The plural slug type. + */ + abstract protected function get_slug_type_plural(); + + /** + * Retrieve the regex to validate the characters that can be used as + * the slug. + * + * @return string Regular expression. + */ + abstract protected function get_valid_characters(); + + /** + * Retrieve the max length of a slug. + * + * The length is limited by the SQL field. + * + * @return int The maximum length of a slug. + */ + abstract protected function get_max_length(); + + /** + * Retrieve the reserved names which can not be used by themes and plugins. + * + * @return array Key is reserved name, value irrelevant. + */ + abstract protected function get_reserved_names(); + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + $this->valid_tokens = Tokens::$textStringTokens + Tokens::$heredocTokens + Tokens::$emptyTokens; + return parent::register(); + } + + /** + * Process the parameter of a matched function. + * + * Errors on invalid names when reserved keywords are used, + * the name is too long, or contains invalid characters. + * + * @param int $stackPtr The position of the current token in the stack. + * @param string $group_name The name of the group which was matched. + * @param string $matched_content The token content (function name) which was matched + * in lowercase. + * @param array $parameters Array with information about the parameters. + * + * @return void + */ + public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { + $slug_param = PassedParameters::getParameterFromStack( + $parameters, + 1, + $this->target_functions[ $matched_content ] + ); + if ( false === $slug_param || '' === $slug_param['clean'] ) { + // Error for using empty slug. + $this->phpcsFile->addError( + '%s() called without a %s slug. The slug must be a non-empty string.', + false === $slug_param ? $stackPtr : $slug_param['start'], + 'Empty', + array( + $matched_content, + $this->slug_type, + ) + ); + return; + } + + $string_start = $this->phpcsFile->findNext( Collections::textStringStartTokens(), $slug_param['start'], ( $slug_param['end'] + 1 ) ); + $string_pos = $this->phpcsFile->findNext( Tokens::$textStringTokens, $slug_param['start'], ( $slug_param['end'] + 1 ) ); + + $has_invalid_tokens = $this->phpcsFile->findNext( $this->valid_tokens, $slug_param['start'], ( $slug_param['end'] + 1 ), true ); + if ( false !== $has_invalid_tokens || false === $string_pos ) { + // Check for non string based slug parameter (we cannot determine if this is valid). + $this->phpcsFile->addWarning( + 'The %s slug is not a string literal. It is not possible to automatically determine the validity of this slug. Found: %s.', + $stackPtr, + 'NotStringLiteral', + array( + $this->slug_type, + $slug_param['clean'], + ), + 3 + ); + return; + } + + $slug = TextStrings::getCompleteTextString( $this->phpcsFile, $string_start ); + if ( isset( Tokens::$heredocTokens[ $this->tokens[ $string_start ]['code'] ] ) ) { + // Trim off potential indentation from PHP 7.3 flexible heredoc/nowdoc content. + $slug = ltrim( $slug ); + } + + // Warn for dynamic parts in the slug parameter. + if ( 'T_DOUBLE_QUOTED_STRING' === $this->tokens[ $string_pos ]['type'] + || ( 'T_HEREDOC' === $this->tokens[ $string_pos ]['type'] + && strpos( $this->tokens[ $string_pos ]['content'], '$' ) !== false ) + ) { + $this->phpcsFile->addWarning( + 'The %s slug may, or may not, get too long with dynamic contents and could contain invalid characters. Found: "%s".', + $string_pos, + 'PartiallyDynamic', + array( + $this->slug_type, + $slug, + ) + ); + $slug = TextStrings::stripEmbeds( $slug ); + } + + if ( preg_match( $this->valid_characters, $slug ) === 0 ) { + // Error for invalid characters. + $this->phpcsFile->addError( + '%s() called with invalid %s "%s". %s contains invalid characters. Only lowercase alphanumeric characters, dashes, and underscores are allowed.', + $string_pos, + 'InvalidCharacters', + array( + $matched_content, + $this->slug_type, + ucfirst( $this->slug_type ), + $slug, + ) + ); + } + + if ( isset( $this->reserved_names[ $slug ] ) ) { + // Error for using reserved slug names. + $this->phpcsFile->addError( + '%s() called with reserved %s "%s". Reserved %s should not be used as they interfere with the functioning of WordPress itself.', + $string_pos, + 'Reserved', + array( + $matched_content, + $this->slug_type, + $slug, + $this->slug_type_plural, + ) + ); + } elseif ( stripos( $slug, 'wp_' ) === 0 ) { + // Error for using reserved slug prefix. + $this->phpcsFile->addError( + 'The %s passed to %s() uses a prefix reserved for WordPress itself. Found: "%s".', + $string_pos, + 'ReservedPrefix', + array( + $this->slug_type, + $matched_content, + $slug, + ) + ); + } + + // Error for slugs that are too long. + if ( strlen( $slug ) > $this->max_length ) { + $this->phpcsFile->addError( + 'A %s slug must not exceed %d characters. Found: "%s" (%d characters).', + $string_pos, + 'TooLong', + array( + $this->slug_type, + $this->max_length, + $slug, + strlen( $slug ), + ) + ); + } + } +} diff --git a/WordPress/Docs/NamingConventions/ValidTaxonomySlugStandard.xml b/WordPress/Docs/NamingConventions/ValidTaxonomySlugStandard.xml new file mode 100644 index 000000000..2d45e8a7e --- /dev/null +++ b/WordPress/Docs/NamingConventions/ValidTaxonomySlugStandard.xml @@ -0,0 +1,121 @@ + + + + + + + + 'my_short_slug', + array() +); + ]]> + + + 'my_very_own_taxonomy_is_much_too_long', + array() +); + ]]> + + + + + + + + 'my_taxonomy_slug', + array() +); + ]]> + + + 'my/taxonomy/slug', + array() +); + ]]> + + + + + + + + 'my_taxonomy_active', + array() +); + ]]> + + + "my_taxonomy_{$status}", + array() +); + ]]> + + + + + + + + 'prefixed_post_tag', + array() +); + ]]> + + + 'post_tag', + array() +); + ]]> + + + + + + + + 'prefixed_post_tag', + array() +); + ]]> + + + 'wp_post_tag', + array() +); + ]]> + + + diff --git a/WordPress/Helpers/WPReservedKeywordHelper.php b/WordPress/Helpers/WPReservedKeywordHelper.php new file mode 100644 index 000000000..03d18ad81 --- /dev/null +++ b/WordPress/Helpers/WPReservedKeywordHelper.php @@ -0,0 +1,187 @@ + Key is reserved post type name, value irrelevant. + */ + private static $post_types = array( + 'action' => true, // Not a WP post type, but prevents other problems. + 'attachment' => true, + 'author' => true, // Not a WP post type, but prevents other problems. + 'custom_css' => true, + 'customize_changeset' => true, + 'nav_menu_item' => true, + 'oembed_cache' => true, + 'order' => true, // Not a WP post type, but prevents other problems. + 'page' => true, + 'post' => true, + 'revision' => true, + 'theme' => true, // Not a WP post type, but prevents other problems. + 'user_request' => true, + 'wp_block' => true, + 'wp_font_face' => true, + 'wp_font_family' => true, + 'wp_global_styles' => true, + 'wp_navigation' => true, + 'wp_template' => true, + 'wp_template_part' => true, + ); + + /** + * Array of reserved taxonomy names which can not be used by themes and plugins. + * + * Source: {@link https://developer.wordpress.org/reference/functions/register_taxonomy/#reserved-terms} + * + * {@internal To be updated after every major release.} + * + * @var array Key is reserved taxonomy name, value irrelevant. + */ + private static $terms = array( + 'attachment' => true, + 'attachment_id' => true, + 'author' => true, + 'author_name' => true, + 'calendar' => true, + 'cat' => true, + 'category' => true, + 'category__and' => true, + 'category__in' => true, + 'category__not_in' => true, + 'category_name' => true, + 'comments_per_page' => true, + 'comments_popup' => true, + 'custom' => true, + 'customize_messenger_channel' => true, + 'customized' => true, + 'cpage' => true, + 'day' => true, + 'debug' => true, + 'embed' => true, + 'error' => true, + 'exact' => true, + 'feed' => true, + 'fields' => true, + 'hour' => true, + 'link_category' => true, + 'm' => true, + 'minute' => true, + 'monthnum' => true, + 'more' => true, + 'name' => true, + 'nav_menu' => true, + 'nonce' => true, + 'nopaging' => true, + 'offset' => true, + 'order' => true, + 'orderby' => true, + 'p' => true, + 'page' => true, + 'page_id' => true, + 'paged' => true, + 'pagename' => true, + 'pb' => true, + 'perm' => true, + 'post' => true, + 'post__in' => true, + 'post__not_in' => true, + 'post_format' => true, + 'post_mime_type' => true, + 'post_status' => true, + 'post_tag' => true, + 'post_type' => true, + 'posts' => true, + 'posts_per_archive_page' => true, + 'posts_per_page' => true, + 'preview' => true, + 'robots' => true, + 's' => true, + 'search' => true, + 'second' => true, + 'sentence' => true, + 'showposts' => true, + 'static' => true, + 'status' => true, + 'subpost' => true, + 'subpost_id' => true, + 'tag' => true, + 'tag__and' => true, + 'tag__in' => true, + 'tag__not_in' => true, + 'tag_id' => true, + 'tag_slug__and' => true, + 'tag_slug__in' => true, + 'taxonomy' => true, + 'tb' => true, + 'term' => true, + 'terms' => true, + 'theme' => true, + 'title' => true, + 'type' => true, + 'types' => true, + 'w' => true, + 'withcomments' => true, + 'withoutcomments' => true, + 'year' => true, + ); + + /** + * Verify if a given keyword is a reserved post type name. + * + * @param string $name The keyword to be checked. + * + * @return bool + */ + public static function is_reserved_post_type( $name ) { + + return isset( self::$post_types[ $name ] ); + } + + /** + * Verify if a given keyword is a reserved taxonomy name. + * + * @param string $name The keyword to be checked. + * + * @return bool + */ + public static function is_reserved_term( $name ) { + + return isset( self::$terms[ $name ] ) + || isset( self::$post_types[ $name ] ); + } + + /** + * Retrieve an array with the reserved post type names. + * + * @return array Array with the post type names as keys. The value is irrelevant. + */ + public static function get_post_types() { + return self::$post_types; + } + + /** + * Retrieve an array with the reserved taxonomy names. + * + * @return array Array with the taxonomy names as keys. The value is irrelevant. + */ + public static function get_terms() { + return array_merge( self::$post_types, self::$terms ); + } +} diff --git a/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php b/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php index 9b3d3db4b..b14fe0c0c 100644 --- a/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php +++ b/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php @@ -9,222 +9,78 @@ namespace WordPressCS\WordPress\Sniffs\NamingConventions; -use PHP_CodeSniffer\Util\Tokens; -use PHPCSUtils\Tokens\Collections; -use PHPCSUtils\Utils\PassedParameters; -use PHPCSUtils\Utils\TextStrings; -use WordPressCS\WordPress\AbstractFunctionParameterSniff; +use WordPressCS\WordPress\AbstractValidSlugSniff; +use WordPressCS\WordPress\Helpers\WPReservedKeywordHelper; /** * Validates post type names. * - * Checks the post type slug for invalid characters, long function names - * and reserved names. + * Checks post type slugs for the presence of invalid characters, excessive + * length, and reserved keywords. * * @link https://developer.wordpress.org/reference/functions/register_post_type/ * * @since 2.2.0 */ -final class ValidPostTypeSlugSniff extends AbstractFunctionParameterSniff { +final class ValidPostTypeSlugSniff extends AbstractValidSlugSniff { /** - * Max length of a post type name is limited by the SQL field. + * Retrieve function and parameter(s) pairs this sniff is looking for. * - * @since 2.2.0 - * - * @var int - */ - const POST_TYPE_MAX_LENGTH = 20; - - /** - * Regex to validate the characters that can be used as the post type slug. - * - * @link https://developer.wordpress.org/reference/functions/register_post_type/ - * @since 2.2.0 - * @since 3.0.0 Renamed from `POST_TYPE_CHARACTER_WHITELIST` to `VALID_POST_TYPE_CHARACTERS`. - * - * @var string + * @return array> Function parameter(s) pairs. */ - const VALID_POST_TYPE_CHARACTERS = '/^[a-z0-9_-]+$/'; + protected function get_target_functions() { + return array( + 'register_post_type' => array( 'post_type' ), + ); + } /** - * Array of functions that must be checked. - * - * @since 2.2.0 + * Retrieve the slug type. * - * @var array Key is function name, value irrelevant. + * @return string The slug type. */ - protected $target_functions = array( - 'register_post_type' => true, - ); + protected function get_slug_type() { + return 'post type'; + } /** - * Array of reserved post type names which can not be used by themes and plugins. - * - * Source: {@link https://developer.wordpress.org/reference/functions/register_post_type/#reserved-post-types} + * Retrieve the plural slug type. * - * {@internal To be updated after every major release. Last updated for WordPress 6.5-RC3.} - * - * @since 2.2.0 - * - * @var array Key is reserved post type name, value irrelevant. + * @return string The plural slug type. */ - protected $reserved_names = array( - 'action' => true, // Not a WP post type, but prevents other problems. - 'attachment' => true, - 'author' => true, // Not a WP post type, but prevents other problems. - 'custom_css' => true, - 'customize_changeset' => true, - 'nav_menu_item' => true, - 'oembed_cache' => true, - 'order' => true, // Not a WP post type, but prevents other problems. - 'page' => true, - 'post' => true, - 'revision' => true, - 'theme' => true, // Not a WP post type, but prevents other problems. - 'user_request' => true, - 'wp_block' => true, - 'wp_font_face' => true, - 'wp_font_family' => true, - 'wp_global_styles' => true, - 'wp_navigation' => true, - 'wp_template' => true, - 'wp_template_part' => true, - ); + protected function get_slug_type_plural() { + return 'post types'; + } /** - * All valid tokens for in the first parameter of register_post_type(). - * - * Set in `register()`. + * Retrieve regex to validate the characters that can be used as the + * post type slug. * - * @since 2.2.0 + * @link https://developer.wordpress.org/reference/functions/register_post_type/ * - * @var array + * @var string */ - private $valid_tokens = array(); + protected function get_valid_characters() { + return '/^[a-z0-9_-]+$/'; + } /** - * Returns an array of tokens this test wants to listen for. + * Retrieve max length of a post type name. * - * @since 2.2.0 - * - * @return array + * @var int */ - public function register() { - $this->valid_tokens = Tokens::$textStringTokens + Tokens::$heredocTokens + Tokens::$emptyTokens; - return parent::register(); + protected function get_max_length() { + return 20; } /** - * Process the parameter of a matched function. + * Retrieve the reserved post type names which can not be used + * by themes and plugins. * - * Errors on invalid post type names when reserved keywords are used, - * the post type is too long, or contains invalid characters. - * - * @since 2.2.0 - * - * @param int $stackPtr The position of the current token in the stack. - * @param string $group_name The name of the group which was matched. - * @param string $matched_content The token content (function name) which was matched - * in lowercase. - * @param array $parameters Array with information about the parameters. - * - * @return void + * @return array */ - public function process_parameters( $stackPtr, $group_name, $matched_content, $parameters ) { - $post_type_param = PassedParameters::getParameterFromStack( $parameters, 1, 'post_type' ); - if ( false === $post_type_param || '' === $post_type_param['clean'] ) { - // Error for using empty slug. - $this->phpcsFile->addError( - 'register_post_type() called without a post type slug. The slug must be a non-empty string.', - false === $post_type_param ? $stackPtr : $post_type_param['start'], - 'Empty' - ); - return; - } - - $string_start = $this->phpcsFile->findNext( Collections::textStringStartTokens(), $post_type_param['start'], ( $post_type_param['end'] + 1 ) ); - $string_pos = $this->phpcsFile->findNext( Tokens::$textStringTokens, $post_type_param['start'], ( $post_type_param['end'] + 1 ) ); - - $has_invalid_tokens = $this->phpcsFile->findNext( $this->valid_tokens, $post_type_param['start'], ( $post_type_param['end'] + 1 ), true ); - if ( false !== $has_invalid_tokens || false === $string_pos ) { - // Check for non string based slug parameter (we cannot determine if this is valid). - $this->phpcsFile->addWarning( - 'The post type slug is not a string literal. It is not possible to automatically determine the validity of this slug. Found: %s.', - $stackPtr, - 'NotStringLiteral', - array( - $post_type_param['clean'], - ), - 3 - ); - return; - } - - $post_type = TextStrings::getCompleteTextString( $this->phpcsFile, $string_start ); - if ( isset( Tokens::$heredocTokens[ $this->tokens[ $string_start ]['code'] ] ) ) { - // Trim off potential indentation from PHP 7.3 flexible heredoc/nowdoc content. - $post_type = ltrim( $post_type ); - } - - $data = array( - $post_type, - ); - - // Warn for dynamic parts in the slug parameter. - if ( 'T_DOUBLE_QUOTED_STRING' === $this->tokens[ $string_pos ]['type'] - || ( 'T_HEREDOC' === $this->tokens[ $string_pos ]['type'] - && strpos( $this->tokens[ $string_pos ]['content'], '$' ) !== false ) - ) { - $this->phpcsFile->addWarning( - 'The post type slug may, or may not, get too long with dynamic contents and could contain invalid characters. Found: "%s".', - $string_pos, - 'PartiallyDynamic', - $data - ); - $post_type = TextStrings::stripEmbeds( $post_type ); - } - - if ( preg_match( self::VALID_POST_TYPE_CHARACTERS, $post_type ) === 0 ) { - // Error for invalid characters. - $this->phpcsFile->addError( - 'register_post_type() called with invalid post type "%s". Post type contains invalid characters. Only lowercase alphanumeric characters, dashes, and underscores are allowed.', - $string_pos, - 'InvalidCharacters', - $data - ); - } - - if ( isset( $this->reserved_names[ $post_type ] ) ) { - // Error for using reserved slug names. - $this->phpcsFile->addError( - 'register_post_type() called with reserved post type "%s". Reserved post types should not be used as they interfere with the functioning of WordPress itself.', - $string_pos, - 'Reserved', - $data - ); - } elseif ( stripos( $post_type, 'wp_' ) === 0 ) { - // Error for using reserved slug prefix. - $this->phpcsFile->addError( - 'The post type passed to register_post_type() uses a prefix reserved for WordPress itself. Found: "%s".', - $string_pos, - 'ReservedPrefix', - $data - ); - } - - // Error for slugs that are too long. - if ( strlen( $post_type ) > self::POST_TYPE_MAX_LENGTH ) { - $this->phpcsFile->addError( - 'A post type slug must not exceed %d characters. Found: "%s" (%d characters).', - $string_pos, - 'TooLong', - array( - self::POST_TYPE_MAX_LENGTH, - $post_type, - strlen( $post_type ), - ) - ); - } + protected function get_reserved_names() { + return WPReservedKeywordHelper::get_post_types(); } } diff --git a/WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php b/WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php new file mode 100644 index 000000000..0435c2078 --- /dev/null +++ b/WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php @@ -0,0 +1,84 @@ +> Function parameter(s) pairs. + */ + protected function get_target_functions() { + return array( + 'register_taxonomy' => array( 'taxonomy' ), + ); + } + + /** + * Retrieve the slug type. + * + * @return string The slug type. + */ + protected function get_slug_type() { + return 'taxonomy'; + } + + /** + * Retrieve the plural slug type. + * + * @return string The plural slug type. + */ + protected function get_slug_type_plural() { + return 'taxonomies'; + } + + /** + * Retrieve regex to validate the characters that can be used as the + * taxonomy slug. + * + * @link https://developer.wordpress.org/reference/functions/register_taxonomy/ + * + * @var string + */ + protected function get_valid_characters() { + return '/^[a-z0-9_-]+$/'; + } + + /** + * Retrieve max length of a taxonomy name. + * + * @var int + */ + protected function get_max_length() { + return 32; + } + + /** + * Retrieve the reserved taxonomy names which can not be used + * by themes and plugins. + * + * @return array + */ + protected function get_reserved_names() { + return WPReservedKeywordHelper::get_terms(); + } +} diff --git a/WordPress/Tests/NamingConventions/ValidTaxonomySlugUnitTest.1.inc b/WordPress/Tests/NamingConventions/ValidTaxonomySlugUnitTest.1.inc new file mode 100644 index 000000000..42a5c2b5d --- /dev/null +++ b/WordPress/Tests/NamingConventions/ValidTaxonomySlugUnitTest.1.inc @@ -0,0 +1,70 @@ +get_taxonomy_id() ); // Non string literal. Warning with severity: 3 + +register_taxonomy( null, array() ); // Non string literal. Warning with severity: 3 +register_taxonomy( 1000, array() ); // Non string literal. Warning with severity: 3 + +register_taxonomy( 'wp_', array() ); // Bad. Reserved prefix. +register_taxonomy( 'wp_taxonomy', array() ); // Bad. Reserved prefix. + +register_taxonomy( '', array() ); // Bad. Empty taxonomy slug. +register_taxonomy( /*comment*/, array() ); // Bad. No taxonomy slug. + +register_taxonomy( 'taxonomy_1', array() ); // OK. + +register_taxonomy( <<warningSeverity = 3; + } + + /** + * Returns the lines where errors should occur. + * + * @param string $testFile The name of the file being tested. + * + * @return array Key is the line number, value is the number of expected errors. + */ + public function getErrorList( $testFile = '' ) { + switch ( $testFile ) { + case 'ValidTaxonomySlugUnitTest.1.inc': + return array( + 5 => 1, + 6 => 1, + 7 => 1, + 8 => 1, + 20 => 1, + 36 => 1, + 37 => 1, + 39 => 1, + 40 => 1, + 49 => 1, + 50 => 2, + 52 => 1, + 62 => 1, + 64 => 1, + ); + + case 'ValidTaxonomySlugUnitTest.2.inc': + // These tests will only yield reliable results when PHPCS is run on PHP 7.3 or higher. + if ( \PHP_VERSION_ID < 70300 ) { + return array(); + } + + return array( + 17 => 1, + ); + + default: + return array(); + } + } + + /** + * Returns the lines where warnings should occur. + * + * @param string $testFile The name of the file being tested. + * + * @return array Key is the line number, value is the number of expected warnings. + */ + public function getWarningList( $testFile = '' ) { + switch ( $testFile ) { + case 'ValidTaxonomySlugUnitTest.1.inc': + return array( + 24 => 1, + 27 => 1, + 28 => 1, + 29 => 1, + 30 => 1, + 31 => 1, + 33 => 1, + 34 => 1, + 45 => 1, + 49 => 1, + 55 => 1, + 56 => 1, + 67 => 1, + ); + + case 'ValidTaxonomySlugUnitTest.2.inc': + // These tests will only yield reliable results when PHPCS is run on PHP 7.3 or higher. + if ( \PHP_VERSION_ID < 70300 ) { + return array(); + } + + return array( + 7 => 1, + ); + + default: + return array(); + } + } +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist index a5f12e738..b50909b31 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -25,6 +25,7 @@ ./WordPress/AbstractClassRestrictionsSniff.php ./WordPress/AbstractFunctionParameterSniff.php ./WordPress/AbstractFunctionRestrictionsSniff.php + ./WordPress/AbstractValidSlugSniff.php ./WordPress/Sniffs/ ./WordPress/Helpers/ From 9b101b289bcc14b95a0af559f2b4910bb1dba029 Mon Sep 17 00:00:00 2001 From: Marian <42134098+IanDelMar@users.noreply.github.com> Date: Tue, 10 Sep 2024 05:57:24 +0200 Subject: [PATCH 02/20] Fix return tag --- WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php | 4 ++-- WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php b/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php index b14fe0c0c..76b5320f8 100644 --- a/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php +++ b/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php @@ -59,7 +59,7 @@ protected function get_slug_type_plural() { * * @link https://developer.wordpress.org/reference/functions/register_post_type/ * - * @var string + * @return string */ protected function get_valid_characters() { return '/^[a-z0-9_-]+$/'; @@ -68,7 +68,7 @@ protected function get_valid_characters() { /** * Retrieve max length of a post type name. * - * @var int + * @return int */ protected function get_max_length() { return 20; diff --git a/WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php b/WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php index 0435c2078..61e5cf96b 100644 --- a/WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php +++ b/WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php @@ -57,7 +57,7 @@ protected function get_slug_type_plural() { * * @link https://developer.wordpress.org/reference/functions/register_taxonomy/ * - * @var string + * @return string */ protected function get_valid_characters() { return '/^[a-z0-9_-]+$/'; @@ -66,7 +66,7 @@ protected function get_valid_characters() { /** * Retrieve max length of a taxonomy name. * - * @var int + * @return int */ protected function get_max_length() { return 32; From a5653a324443cf8c1281ed800bbd7625fe2852eb Mon Sep 17 00:00:00 2001 From: IanDelMar <42134098+IanDelMar@users.noreply.github.com> Date: Tue, 10 Sep 2024 17:29:11 +0200 Subject: [PATCH 03/20] Update WordPress/AbstractValidSlugSniff.php Co-authored-by: Juliette <663378+jrfnl@users.noreply.github.com> --- WordPress/AbstractValidSlugSniff.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/AbstractValidSlugSniff.php b/WordPress/AbstractValidSlugSniff.php index 99665c5f6..eb7d396c5 100644 --- a/WordPress/AbstractValidSlugSniff.php +++ b/WordPress/AbstractValidSlugSniff.php @@ -4,7 +4,7 @@ * * @package WPCS\WordPressCodingStandards * @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards - * @license https://opensource.org/licenses/MIT MITnamespace WordPressCS\WordPress; + * @license https://opensource.org/licenses/MIT MIT */ namespace WordPressCS\WordPress; From dcddda1486bf5d08ae9d36d0fd66f75ee8e8269a Mon Sep 17 00:00:00 2001 From: IanDelMar <42134098+IanDelMar@users.noreply.github.com> Date: Tue, 10 Sep 2024 17:29:19 +0200 Subject: [PATCH 04/20] Update WordPress-Extra/ruleset.xml Co-authored-by: Juliette <663378+jrfnl@users.noreply.github.com> --- WordPress-Extra/ruleset.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress-Extra/ruleset.xml b/WordPress-Extra/ruleset.xml index 9dcf94c08..068162bf9 100644 --- a/WordPress-Extra/ruleset.xml +++ b/WordPress-Extra/ruleset.xml @@ -132,7 +132,7 @@ - + From 265d46ff6ab43331f6a04b9a317348a14b392a6b Mon Sep 17 00:00:00 2001 From: IanDelMar <42134098+IanDelMar@users.noreply.github.com> Date: Tue, 10 Sep 2024 17:31:01 +0200 Subject: [PATCH 05/20] Update WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php Co-authored-by: Juliette <663378+jrfnl@users.noreply.github.com> --- WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php b/WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php index 61e5cf96b..88ae27e13 100644 --- a/WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php +++ b/WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php @@ -16,7 +16,7 @@ * Validates taxonomy names. * * Checks taxonomy slugs for the presence of invalid characters, excessive - * length, and reserved keywords. + * length, and reserved names. * * @link https://developer.wordpress.org/reference/functions/register_taxonomy/ */ From 5b7267ee0f4432ede03352fcfa8f67be45b51fcb Mon Sep 17 00:00:00 2001 From: IanDelMar <42134098+IanDelMar@users.noreply.github.com> Date: Tue, 10 Sep 2024 17:31:15 +0200 Subject: [PATCH 06/20] Update WordPress/AbstractValidSlugSniff.php Co-authored-by: Juliette <663378+jrfnl@users.noreply.github.com> --- WordPress/AbstractValidSlugSniff.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/AbstractValidSlugSniff.php b/WordPress/AbstractValidSlugSniff.php index eb7d396c5..4769f77d0 100644 --- a/WordPress/AbstractValidSlugSniff.php +++ b/WordPress/AbstractValidSlugSniff.php @@ -52,7 +52,7 @@ abstract class AbstractValidSlugSniff extends AbstractFunctionParameterSniff { protected $valid_characters; /** - * Array of reserved names which can not be used by themes and plugins. + * Array of reserved names for a specific slug type. * * @var array Key is reserved name, value irrelevant. */ From 4a1b3d0b488ec36d0a04a48d40ed3010e1b72c2e Mon Sep 17 00:00:00 2001 From: IanDelMar <42134098+IanDelMar@users.noreply.github.com> Date: Tue, 10 Sep 2024 17:53:47 +0200 Subject: [PATCH 07/20] Update WordPress/Docs/NamingConventions/ValidTaxonomySlugStandard.xml Co-authored-by: Juliette <663378+jrfnl@users.noreply.github.com> --- WordPress/Docs/NamingConventions/ValidTaxonomySlugStandard.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/Docs/NamingConventions/ValidTaxonomySlugStandard.xml b/WordPress/Docs/NamingConventions/ValidTaxonomySlugStandard.xml index 2d45e8a7e..83762acb1 100644 --- a/WordPress/Docs/NamingConventions/ValidTaxonomySlugStandard.xml +++ b/WordPress/Docs/NamingConventions/ValidTaxonomySlugStandard.xml @@ -74,7 +74,7 @@ register_taxonomy( From dc545ee1208911673c02704a465c64ade64f951d Mon Sep 17 00:00:00 2001 From: IanDelMar <42134098+IanDelMar@users.noreply.github.com> Date: Tue, 10 Sep 2024 18:23:16 +0200 Subject: [PATCH 08/20] Update WordPress/Docs/NamingConventions/ValidTaxonomySlugStandard.xml Co-authored-by: Juliette <663378+jrfnl@users.noreply.github.com> --- WordPress/Docs/NamingConventions/ValidTaxonomySlugStandard.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/Docs/NamingConventions/ValidTaxonomySlugStandard.xml b/WordPress/Docs/NamingConventions/ValidTaxonomySlugStandard.xml index 83762acb1..25f525b2f 100644 --- a/WordPress/Docs/NamingConventions/ValidTaxonomySlugStandard.xml +++ b/WordPress/Docs/NamingConventions/ValidTaxonomySlugStandard.xml @@ -86,7 +86,7 @@ register_taxonomy( ); ]]> - + 'post_tag', From 2150d29145a35a0438bcbd3af437c2f12f31e411 Mon Sep 17 00:00:00 2001 From: IanDelMar <42134098+IanDelMar@users.noreply.github.com> Date: Tue, 10 Sep 2024 18:28:01 +0200 Subject: [PATCH 09/20] Update WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php Co-authored-by: Juliette <663378+jrfnl@users.noreply.github.com> --- WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php b/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php index 76b5320f8..7f57aab30 100644 --- a/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php +++ b/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php @@ -16,7 +16,7 @@ * Validates post type names. * * Checks post type slugs for the presence of invalid characters, excessive - * length, and reserved keywords. + * length, and reserved names. * * @link https://developer.wordpress.org/reference/functions/register_post_type/ * From b829a79cbd1771ed50dbe2fadcae0f8f38174f58 Mon Sep 17 00:00:00 2001 From: IanDelMar <42134098+IanDelMar@users.noreply.github.com> Date: Tue, 10 Sep 2024 18:58:57 +0200 Subject: [PATCH 10/20] Update WordPress/Helpers/WPReservedKeywordHelper.php Co-authored-by: Juliette <663378+jrfnl@users.noreply.github.com> --- WordPress/Helpers/WPReservedKeywordHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/Helpers/WPReservedKeywordHelper.php b/WordPress/Helpers/WPReservedKeywordHelper.php index 03d18ad81..80b66d78c 100644 --- a/WordPress/Helpers/WPReservedKeywordHelper.php +++ b/WordPress/Helpers/WPReservedKeywordHelper.php @@ -12,7 +12,7 @@ /** * Helper utilities for recognizing WP reserved keywords. */ -final class WPReservedKeywordHelper { +final class WPReservedNamesHelper { /** * Array of reserved post type names which can not be used by themes and plugins. * From ce18b1cb9f089d36bcb9d620c9ff2892ed06f21b Mon Sep 17 00:00:00 2001 From: Marian <42134098+IanDelMar@users.noreply.github.com> Date: Tue, 10 Sep 2024 18:59:24 +0200 Subject: [PATCH 11/20] Rename WPReservedKeywordHelper --- .github/release-checklist.md | 4 ++-- WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php | 4 ++-- WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/release-checklist.md b/.github/release-checklist.md index 89cfbd9e0..92f93e024 100644 --- a/.github/release-checklist.md +++ b/.github/release-checklist.md @@ -28,8 +28,8 @@ PR for tracking changes for the x.x.x release. Target release date: **DOW MONTH - [ ] `$pluggable_functions` in `WordPress.NamingConventions.PrefixAllGlobals` - PR #xxx - [ ] `$pluggable_classes` in `WordPress.NamingConventions.PrefixAllGlobals` - PR #xxx - [ ] `$target_functions` in `WordPress.Security.PluginMenuSlug` - PR #xxx - - [ ] `$post_types` in `WPReservedKeywordHelper` - PR #xxx - - [ ] `$terms` in `WPReservedKeywordHelper` - PR #xxx + - [ ] `$post_types` in `WPReservedNamesHelper` - PR #xxx + - [ ] `$terms` in `WPReservedNamesHelper` - PR #xxx - [ ] `$wp_time_constants` in `WordPress.WP.CronInterval` - PR #xxx - [ ] `$known_test_classes` in `IsUnitTestTrait` - PR #xxx - [ ] ...etc... diff --git a/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php b/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php index 7f57aab30..d46c40275 100644 --- a/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php +++ b/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php @@ -10,7 +10,7 @@ namespace WordPressCS\WordPress\Sniffs\NamingConventions; use WordPressCS\WordPress\AbstractValidSlugSniff; -use WordPressCS\WordPress\Helpers\WPReservedKeywordHelper; +use WordPressCS\WordPress\Helpers\WPReservedNamesHelper; /** * Validates post type names. @@ -81,6 +81,6 @@ protected function get_max_length() { * @return array */ protected function get_reserved_names() { - return WPReservedKeywordHelper::get_post_types(); + return WPReservedNamesHelper::get_post_types(); } } diff --git a/WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php b/WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php index 88ae27e13..2ec332250 100644 --- a/WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php +++ b/WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php @@ -10,7 +10,7 @@ namespace WordPressCS\WordPress\Sniffs\NamingConventions; use WordPressCS\WordPress\AbstractValidSlugSniff; -use WordPressCS\WordPress\Helpers\WPReservedKeywordHelper; +use WordPressCS\WordPress\Helpers\WPReservedNamesHelper; /** * Validates taxonomy names. @@ -79,6 +79,6 @@ protected function get_max_length() { * @return array */ protected function get_reserved_names() { - return WPReservedKeywordHelper::get_terms(); + return WPReservedNamesHelper::get_terms(); } } From 04922b8e6c5bfc79ea58fd83836d0706cadaf45e Mon Sep 17 00:00:00 2001 From: IanDelMar <42134098+IanDelMar@users.noreply.github.com> Date: Tue, 10 Sep 2024 19:00:37 +0200 Subject: [PATCH 12/20] Update WordPress/AbstractValidSlugSniff.php Co-authored-by: Juliette <663378+jrfnl@users.noreply.github.com> --- WordPress/AbstractValidSlugSniff.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/AbstractValidSlugSniff.php b/WordPress/AbstractValidSlugSniff.php index 4769f77d0..bc600ea67 100644 --- a/WordPress/AbstractValidSlugSniff.php +++ b/WordPress/AbstractValidSlugSniff.php @@ -143,7 +143,7 @@ public function register() { /** * Process the parameter of a matched function. * - * Errors on invalid names when reserved keywords are used, + * Errors on invalid names when reserved names are used, * the name is too long, or contains invalid characters. * * @param int $stackPtr The position of the current token in the stack. From 5ec64ac90f9a386598c1abec3817748759ad17ed Mon Sep 17 00:00:00 2001 From: Marian <42134098+IanDelMar@users.noreply.github.com> Date: Tue, 10 Sep 2024 19:04:58 +0200 Subject: [PATCH 13/20] Rename WPReservedNamesHelper file --- .../{WPReservedKeywordHelper.php => WPReservedNamesHelper.php} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename WordPress/Helpers/{WPReservedKeywordHelper.php => WPReservedNamesHelper.php} (100%) diff --git a/WordPress/Helpers/WPReservedKeywordHelper.php b/WordPress/Helpers/WPReservedNamesHelper.php similarity index 100% rename from WordPress/Helpers/WPReservedKeywordHelper.php rename to WordPress/Helpers/WPReservedNamesHelper.php From 4e6f7f77f658de4484f1bf882e704dd7a5fcd18d Mon Sep 17 00:00:00 2001 From: Marian <42134098+IanDelMar@users.noreply.github.com> Date: Tue, 10 Sep 2024 19:12:44 +0200 Subject: [PATCH 14/20] Use name instead of keyword --- WordPress-Extra/ruleset.xml | 2 +- WordPress/AbstractValidSlugSniff.php | 2 +- .../ValidPostTypeSlugStandard.xml | 64 +++++++++---------- WordPress/Helpers/WPReservedNamesHelper.php | 12 ++-- .../ValidPostTypeSlugUnitTest.1.inc | 2 +- .../ValidTaxonomySlugUnitTest.1.inc | 2 +- 6 files changed, 41 insertions(+), 43 deletions(-) diff --git a/WordPress-Extra/ruleset.xml b/WordPress-Extra/ruleset.xml index 068162bf9..2f10ba81d 100644 --- a/WordPress-Extra/ruleset.xml +++ b/WordPress-Extra/ruleset.xml @@ -129,7 +129,7 @@ - + diff --git a/WordPress/AbstractValidSlugSniff.php b/WordPress/AbstractValidSlugSniff.php index 4769f77d0..0b56e47ad 100644 --- a/WordPress/AbstractValidSlugSniff.php +++ b/WordPress/AbstractValidSlugSniff.php @@ -19,7 +19,7 @@ * Validates names passed to a function call. * * Checks slugs for the presence of invalid characters, excessive length, - * and reserved keywords. + * and reserved names. */ abstract class AbstractValidSlugSniff extends AbstractFunctionParameterSniff { diff --git a/WordPress/Docs/NamingConventions/ValidPostTypeSlugStandard.xml b/WordPress/Docs/NamingConventions/ValidPostTypeSlugStandard.xml index 639dda54e..f770b6870 100644 --- a/WordPress/Docs/NamingConventions/ValidPostTypeSlugStandard.xml +++ b/WordPress/Docs/NamingConventions/ValidPostTypeSlugStandard.xml @@ -11,17 +11,17 @@ 'my_short_slug', - array() +register_post_type( + 'my_short_slug', + array() ); ]]> 'my_own_post_type_too_long', - array() +register_post_type( + 'my_own_post_type_too_long', + array() ); ]]> @@ -34,17 +34,17 @@ register_post_type( 'my_post_type_slug', - array() +register_post_type( + 'my_post_type_slug', + array() ); ]]> 'my/post/type/slug', - array() +register_post_type( + 'my/post/type/slug', + array() ); ]]> @@ -57,40 +57,40 @@ register_post_type( 'my_post_active', - array() +register_post_type( + 'my_post_active', + array() ); ]]> "my_post_{$status}", - array() +register_post_type( + "my_post_{$status}", + array() ); ]]> 'prefixed_author', - array() +register_post_type( + 'prefixed_author', + array() ); ]]> - + 'author', - array() +register_post_type( + 'author', + array() ); ]]> @@ -103,17 +103,17 @@ register_post_type( 'prefixed_author', - array() +register_post_type( + 'prefixed_author', + array() ); ]]> 'wp_author', - array() +register_post_type( + 'wp_author', + array() ); ]]> diff --git a/WordPress/Helpers/WPReservedNamesHelper.php b/WordPress/Helpers/WPReservedNamesHelper.php index 80b66d78c..b518b0f0f 100644 --- a/WordPress/Helpers/WPReservedNamesHelper.php +++ b/WordPress/Helpers/WPReservedNamesHelper.php @@ -10,7 +10,7 @@ namespace WordPressCS\WordPress\Helpers; /** - * Helper utilities for recognizing WP reserved keywords. + * Helper utilities for recognizing WP reserved names. */ final class WPReservedNamesHelper { /** @@ -143,26 +143,24 @@ final class WPReservedNamesHelper { ); /** - * Verify if a given keyword is a reserved post type name. + * Verify if a given name is a reserved post type name. * - * @param string $name The keyword to be checked. + * @param string $name The name to be checked. * * @return bool */ public static function is_reserved_post_type( $name ) { - return isset( self::$post_types[ $name ] ); } /** - * Verify if a given keyword is a reserved taxonomy name. + * Verify if a given name is a reserved taxonomy name. * - * @param string $name The keyword to be checked. + * @param string $name The name to be checked. * * @return bool */ public static function is_reserved_term( $name ) { - return isset( self::$terms[ $name ] ) || isset( self::$post_types[ $name ] ); } diff --git a/WordPress/Tests/NamingConventions/ValidPostTypeSlugUnitTest.1.inc b/WordPress/Tests/NamingConventions/ValidPostTypeSlugUnitTest.1.inc index 5c0ed5729..c994383ea 100644 --- a/WordPress/Tests/NamingConventions/ValidPostTypeSlugUnitTest.1.inc +++ b/WordPress/Tests/NamingConventions/ValidPostTypeSlugUnitTest.1.inc @@ -49,7 +49,7 @@ EOD register_post_type( "my-own-post-type-too-long-{$i}" ); // 1x Error, Too long. 1x Warning, post type may or may not get too long with dynamic contents in the id. register_post_type( 'my/own/post/type/too/long', array() ); // Bad. Invalid chars: "/" and too long. -register_post_type( 'wp_block', array() ); // Bad. Must only error on reserved keyword, not invalid prefix. +register_post_type( 'wp_block', array() ); // Bad. Must only error on reserved name, not invalid prefix. // Test handling of more complex embedded variables and expressions. register_post_type("testing123-${(foo)}-test"); diff --git a/WordPress/Tests/NamingConventions/ValidTaxonomySlugUnitTest.1.inc b/WordPress/Tests/NamingConventions/ValidTaxonomySlugUnitTest.1.inc index 42a5c2b5d..f647cfb63 100644 --- a/WordPress/Tests/NamingConventions/ValidTaxonomySlugUnitTest.1.inc +++ b/WordPress/Tests/NamingConventions/ValidTaxonomySlugUnitTest.1.inc @@ -49,7 +49,7 @@ EOD register_taxonomy( "my-own-taxonomy-toooooooooo-long-{$i}" ); // 1x Error, Too long. 1x Warning, post type may or may not get too long with dynamic contents in the id. register_taxonomy( 'my/own/taxonomy/tooooooooooo/long', array() ); // Bad. Invalid chars: "/" and too long. -register_taxonomy( 'wp_block', array() ); // Bad. Must only error on reserved keyword, not invalid prefix. +register_taxonomy( 'wp_block', array() ); // Bad. Must only error on reserved name, not invalid prefix. // Test handling of more complex embedded variables and expressions. register_taxonomy("testing123-${(foo)}-test"); From c8dbf93be7416d3ce274c2b5e137ba648326c2e5 Mon Sep 17 00:00:00 2001 From: Marian <42134098+IanDelMar@users.noreply.github.com> Date: Tue, 10 Sep 2024 20:30:38 +0200 Subject: [PATCH 15/20] Use private properties --- WordPress/AbstractValidSlugSniff.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/WordPress/AbstractValidSlugSniff.php b/WordPress/AbstractValidSlugSniff.php index 881668e17..3c97c7609 100644 --- a/WordPress/AbstractValidSlugSniff.php +++ b/WordPress/AbstractValidSlugSniff.php @@ -28,35 +28,35 @@ abstract class AbstractValidSlugSniff extends AbstractFunctionParameterSniff { * * @var string */ - protected $slug_type; + private $slug_type; /** * Plural of the slug type. E.g. 'post types' for a post type slug. * * @var string */ - protected $slug_type_plural; + private $slug_type_plural; /** * Max length of a slug is limited by the SQL field. * * @var int */ - protected $max_length; + private $max_length; /** * Regex to validate the characters that can be used as the slug. * * @var string */ - protected $valid_characters; + private $valid_characters; /** * Array of reserved names for a specific slug type. * * @var array Key is reserved name, value irrelevant. */ - protected $reserved_names; + private $reserved_names; /** * All valid tokens for the slug parameter. From 46b5117bada94bb18f9035b38674f0d91e852a8c Mon Sep 17 00:00:00 2001 From: Marian <42134098+IanDelMar@users.noreply.github.com> Date: Tue, 10 Sep 2024 20:38:25 +0200 Subject: [PATCH 16/20] Add "last updated" indicator --- WordPress/Helpers/WPReservedNamesHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/Helpers/WPReservedNamesHelper.php b/WordPress/Helpers/WPReservedNamesHelper.php index b518b0f0f..dfce713d4 100644 --- a/WordPress/Helpers/WPReservedNamesHelper.php +++ b/WordPress/Helpers/WPReservedNamesHelper.php @@ -50,7 +50,7 @@ final class WPReservedNamesHelper { * * Source: {@link https://developer.wordpress.org/reference/functions/register_taxonomy/#reserved-terms} * - * {@internal To be updated after every major release.} + * {@internal To be updated after every major release. Last updated for WordPress 6.6.1.} * * @var array Key is reserved taxonomy name, value irrelevant. */ From ad05b95e8fcbc536ba0fd987a9c981b071f10a5f Mon Sep 17 00:00:00 2001 From: Marian <42134098+IanDelMar@users.noreply.github.com> Date: Wed, 11 Sep 2024 21:04:20 +0200 Subject: [PATCH 17/20] Add since tag --- WordPress/AbstractValidSlugSniff.php | 33 +++++++++++++++++++ WordPress/Helpers/WPReservedNamesHelper.php | 18 ++++++++++ .../ValidPostTypeSlugSniff.php | 12 +++++++ .../ValidTaxonomySlugSniff.php | 14 ++++++++ 4 files changed, 77 insertions(+) diff --git a/WordPress/AbstractValidSlugSniff.php b/WordPress/AbstractValidSlugSniff.php index 3c97c7609..8205a7a9d 100644 --- a/WordPress/AbstractValidSlugSniff.php +++ b/WordPress/AbstractValidSlugSniff.php @@ -20,12 +20,16 @@ * * Checks slugs for the presence of invalid characters, excessive length, * and reserved names. + * + * @since 3.2.0 */ abstract class AbstractValidSlugSniff extends AbstractFunctionParameterSniff { /** * Slug type. E.g. 'post type' for a post type slug. * + * @since 3.2.0 + * * @var string */ private $slug_type; @@ -33,6 +37,8 @@ abstract class AbstractValidSlugSniff extends AbstractFunctionParameterSniff { /** * Plural of the slug type. E.g. 'post types' for a post type slug. * + * @since 3.2.0 + * * @var string */ private $slug_type_plural; @@ -40,6 +46,8 @@ abstract class AbstractValidSlugSniff extends AbstractFunctionParameterSniff { /** * Max length of a slug is limited by the SQL field. * + * @since 3.2.0 + * * @var int */ private $max_length; @@ -47,6 +55,8 @@ abstract class AbstractValidSlugSniff extends AbstractFunctionParameterSniff { /** * Regex to validate the characters that can be used as the slug. * + * @since 3.2.0 + * * @var string */ private $valid_characters; @@ -54,6 +64,8 @@ abstract class AbstractValidSlugSniff extends AbstractFunctionParameterSniff { /** * Array of reserved names for a specific slug type. * + * @since 3.2.0 + * * @var array Key is reserved name, value irrelevant. */ private $reserved_names; @@ -63,6 +75,8 @@ abstract class AbstractValidSlugSniff extends AbstractFunctionParameterSniff { * * Set in `register()`. * + * @since 3.2.0 + * * @var array */ private $valid_tokens = array(); @@ -88,6 +102,8 @@ public function __construct() { * An array of names is supported to allow for functions for which the * parameter names have undergone name changes over time. * + * @since 3.2.0 + * * @return array> Function parameter(s) pairs. */ abstract protected function get_target_functions(); @@ -95,6 +111,8 @@ abstract protected function get_target_functions(); /** * Retrieve the slug type. * + * @since 3.2.0 + * * @return string The slug type. */ abstract protected function get_slug_type(); @@ -102,6 +120,8 @@ abstract protected function get_slug_type(); /** * Retrieve the plural slug type. * + * @since 3.2.0 + * * @return string The plural slug type. */ abstract protected function get_slug_type_plural(); @@ -110,6 +130,8 @@ abstract protected function get_slug_type_plural(); * Retrieve the regex to validate the characters that can be used as * the slug. * + * @since 3.2.0 + * * @return string Regular expression. */ abstract protected function get_valid_characters(); @@ -119,6 +141,8 @@ abstract protected function get_valid_characters(); * * The length is limited by the SQL field. * + * @since 3.2.0 + * * @return int The maximum length of a slug. */ abstract protected function get_max_length(); @@ -126,6 +150,8 @@ abstract protected function get_max_length(); /** * Retrieve the reserved names which can not be used by themes and plugins. * + * @since 3.2.0 + * * @return array Key is reserved name, value irrelevant. */ abstract protected function get_reserved_names(); @@ -133,6 +159,9 @@ abstract protected function get_reserved_names(); /** * Returns an array of tokens this test wants to listen for. * + * @since 2.2.0 + * @since 3.2.0 Moved from the ValidPostTypeSlug Sniff class to this class. + * * @return array */ public function register() { @@ -146,6 +175,10 @@ public function register() { * Errors on invalid names when reserved names are used, * the name is too long, or contains invalid characters. * + * @since 2.2.0 + * @since 3.2.0 Moved from the ValidPostTypeSlug Sniff class to this class and + * modfied for variable target functions and slug restrictions. + * * @param int $stackPtr The position of the current token in the stack. * @param string $group_name The name of the group which was matched. * @param string $matched_content The token content (function name) which was matched diff --git a/WordPress/Helpers/WPReservedNamesHelper.php b/WordPress/Helpers/WPReservedNamesHelper.php index dfce713d4..5ced2f3ae 100644 --- a/WordPress/Helpers/WPReservedNamesHelper.php +++ b/WordPress/Helpers/WPReservedNamesHelper.php @@ -11,6 +11,8 @@ /** * Helper utilities for recognizing WP reserved names. + * + * @since 3.2.0 */ final class WPReservedNamesHelper { /** @@ -20,6 +22,12 @@ final class WPReservedNamesHelper { * * {@internal To be updated after every major release. Last updated for WordPress 6.5-RC3.} * + * @since 2.2.0 + * @since 3.2.0 - Moved from the Sniff class to this class. + * - The property visibility has changed from `protected` to `private static`. + * Use the `get_post_types()` method for access or use the + * `is_reserved_post_type()` method to check if a name is on the list. + * * @var array Key is reserved post type name, value irrelevant. */ private static $post_types = array( @@ -52,6 +60,8 @@ final class WPReservedNamesHelper { * * {@internal To be updated after every major release. Last updated for WordPress 6.6.1.} * + * @since 3.2.0 + * * @var array Key is reserved taxonomy name, value irrelevant. */ private static $terms = array( @@ -145,6 +155,8 @@ final class WPReservedNamesHelper { /** * Verify if a given name is a reserved post type name. * + * @since 3.2.0 + * * @param string $name The name to be checked. * * @return bool @@ -156,6 +168,8 @@ public static function is_reserved_post_type( $name ) { /** * Verify if a given name is a reserved taxonomy name. * + * @since 3.2.0 + * * @param string $name The name to be checked. * * @return bool @@ -168,6 +182,8 @@ public static function is_reserved_term( $name ) { /** * Retrieve an array with the reserved post type names. * + * @since 3.2.0 + * * @return array Array with the post type names as keys. The value is irrelevant. */ public static function get_post_types() { @@ -177,6 +193,8 @@ public static function get_post_types() { /** * Retrieve an array with the reserved taxonomy names. * + * @since 3.2.0 + * * @return array Array with the taxonomy names as keys. The value is irrelevant. */ public static function get_terms() { diff --git a/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php b/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php index d46c40275..857e8913b 100644 --- a/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php +++ b/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php @@ -27,6 +27,8 @@ final class ValidPostTypeSlugSniff extends AbstractValidSlugSniff { /** * Retrieve function and parameter(s) pairs this sniff is looking for. * + * @since 3.2.0 + * * @return array> Function parameter(s) pairs. */ protected function get_target_functions() { @@ -38,6 +40,8 @@ protected function get_target_functions() { /** * Retrieve the slug type. * + * @since 3.2.0 + * * @return string The slug type. */ protected function get_slug_type() { @@ -47,6 +51,8 @@ protected function get_slug_type() { /** * Retrieve the plural slug type. * + * @since 3.2.0 + * * @return string The plural slug type. */ protected function get_slug_type_plural() { @@ -57,6 +63,8 @@ protected function get_slug_type_plural() { * Retrieve regex to validate the characters that can be used as the * post type slug. * + * @since 3.2.0 + * * @link https://developer.wordpress.org/reference/functions/register_post_type/ * * @return string @@ -68,6 +76,8 @@ protected function get_valid_characters() { /** * Retrieve max length of a post type name. * + * @since 3.2.0 + * * @return int */ protected function get_max_length() { @@ -78,6 +88,8 @@ protected function get_max_length() { * Retrieve the reserved post type names which can not be used * by themes and plugins. * + * @since 3.2.0 + * * @return array */ protected function get_reserved_names() { diff --git a/WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php b/WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php index 2ec332250..90b488371 100644 --- a/WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php +++ b/WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php @@ -18,6 +18,8 @@ * Checks taxonomy slugs for the presence of invalid characters, excessive * length, and reserved names. * + * @since 3.2.0 + * * @link https://developer.wordpress.org/reference/functions/register_taxonomy/ */ final class ValidTaxonomySlugSniff extends AbstractValidSlugSniff { @@ -25,6 +27,8 @@ final class ValidTaxonomySlugSniff extends AbstractValidSlugSniff { /** * Retrieve function and parameter(s) pairs this sniff is looking for. * + * @since 3.2.0 + * * @return array> Function parameter(s) pairs. */ protected function get_target_functions() { @@ -36,6 +40,8 @@ protected function get_target_functions() { /** * Retrieve the slug type. * + * @since 3.2.0 + * * @return string The slug type. */ protected function get_slug_type() { @@ -45,6 +51,8 @@ protected function get_slug_type() { /** * Retrieve the plural slug type. * + * @since 3.2.0 + * * @return string The plural slug type. */ protected function get_slug_type_plural() { @@ -55,6 +63,8 @@ protected function get_slug_type_plural() { * Retrieve regex to validate the characters that can be used as the * taxonomy slug. * + * @since 3.2.0 + * * @link https://developer.wordpress.org/reference/functions/register_taxonomy/ * * @return string @@ -66,6 +76,8 @@ protected function get_valid_characters() { /** * Retrieve max length of a taxonomy name. * + * @since 3.2.0 + * * @return int */ protected function get_max_length() { @@ -76,6 +88,8 @@ protected function get_max_length() { * Retrieve the reserved taxonomy names which can not be used * by themes and plugins. * + * @since 3.2.0 + * * @return array */ protected function get_reserved_names() { From dc17ea77e060d03af118a19e3f65bb4a82abfa97 Mon Sep 17 00:00:00 2001 From: Marian <42134098+IanDelMar@users.noreply.github.com> Date: Wed, 11 Sep 2024 21:06:21 +0200 Subject: [PATCH 18/20] Move property setup into register() --- WordPress/AbstractValidSlugSniff.php | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/WordPress/AbstractValidSlugSniff.php b/WordPress/AbstractValidSlugSniff.php index 8205a7a9d..a579b9115 100644 --- a/WordPress/AbstractValidSlugSniff.php +++ b/WordPress/AbstractValidSlugSniff.php @@ -81,20 +81,6 @@ abstract class AbstractValidSlugSniff extends AbstractFunctionParameterSniff { */ private $valid_tokens = array(); - /** - * Constructor. - * - * @since 3.0.0 - */ - public function __construct() { - $this->target_functions = $this->get_target_functions(); - $this->slug_type = $this->get_slug_type(); - $this->slug_type_plural = $this->get_slug_type_plural(); - $this->valid_characters = $this->get_valid_characters(); - $this->max_length = $this->get_max_length(); - $this->reserved_names = $this->get_reserved_names(); - } - /** * Retrieve function and parameter(s) pairs this sniff is looking for. * @@ -160,12 +146,19 @@ abstract protected function get_reserved_names(); * Returns an array of tokens this test wants to listen for. * * @since 2.2.0 - * @since 3.2.0 Moved from the ValidPostTypeSlug Sniff class to this class. + * @since 3.2.0 - Moved from the ValidPostTypeSlug Sniff class to this class. + * - Added setting up properties for target functions and slug details. * * @return array */ public function register() { - $this->valid_tokens = Tokens::$textStringTokens + Tokens::$heredocTokens + Tokens::$emptyTokens; + $this->valid_tokens = Tokens::$textStringTokens + Tokens::$heredocTokens + Tokens::$emptyTokens; + $this->target_functions = $this->get_target_functions(); + $this->slug_type = $this->get_slug_type(); + $this->slug_type_plural = $this->get_slug_type_plural(); + $this->valid_characters = $this->get_valid_characters(); + $this->max_length = $this->get_max_length(); + $this->reserved_names = $this->get_reserved_names(); return parent::register(); } From d9e0ee82a6fe01f5f81cbf57c90a2202ab8a77a6 Mon Sep 17 00:00:00 2001 From: Marian <42134098+IanDelMar@users.noreply.github.com> Date: Wed, 11 Sep 2024 21:11:12 +0200 Subject: [PATCH 19/20] Move max length info to concrete classes --- WordPress/AbstractValidSlugSniff.php | 2 -- WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php | 2 ++ WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/WordPress/AbstractValidSlugSniff.php b/WordPress/AbstractValidSlugSniff.php index a579b9115..34165343c 100644 --- a/WordPress/AbstractValidSlugSniff.php +++ b/WordPress/AbstractValidSlugSniff.php @@ -125,8 +125,6 @@ abstract protected function get_valid_characters(); /** * Retrieve the max length of a slug. * - * The length is limited by the SQL field. - * * @since 3.2.0 * * @return int The maximum length of a slug. diff --git a/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php b/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php index 857e8913b..c38da3158 100644 --- a/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php +++ b/WordPress/Sniffs/NamingConventions/ValidPostTypeSlugSniff.php @@ -76,6 +76,8 @@ protected function get_valid_characters() { /** * Retrieve max length of a post type name. * + * The length is limited by the SQL field. + * * @since 3.2.0 * * @return int diff --git a/WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php b/WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php index 90b488371..8b6819d87 100644 --- a/WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php +++ b/WordPress/Sniffs/NamingConventions/ValidTaxonomySlugSniff.php @@ -76,6 +76,8 @@ protected function get_valid_characters() { /** * Retrieve max length of a taxonomy name. * + * The length is limited by the SQL field. + * * @since 3.2.0 * * @return int From 05f42ca979604a6620900fc5f1638a5419873c18 Mon Sep 17 00:00:00 2001 From: IanDelMar <42134098+IanDelMar@users.noreply.github.com> Date: Wed, 11 Sep 2024 21:16:55 +0200 Subject: [PATCH 20/20] Fix data order Co-authored-by: Juliette <663378+jrfnl@users.noreply.github.com> --- WordPress/AbstractValidSlugSniff.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/AbstractValidSlugSniff.php b/WordPress/AbstractValidSlugSniff.php index 3c97c7609..a96cbe15b 100644 --- a/WordPress/AbstractValidSlugSniff.php +++ b/WordPress/AbstractValidSlugSniff.php @@ -225,8 +225,8 @@ public function process_parameters( $stackPtr, $group_name, $matched_content, $p array( $matched_content, $this->slug_type, - ucfirst( $this->slug_type ), $slug, + ucfirst( $this->slug_type ), ) ); }