Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New WPHookHelper utility class, incl PHP 8.0+ named param helper #2148

Merged
merged 3 commits into from
Dec 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions WordPress/Helpers/WPHookHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<?php
/**
* WordPress Coding Standard.
*
* @package WPCS\WordPressCodingStandards
* @link https://github.com/WordPress/WordPress-Coding-Standards
* @license https://opensource.org/licenses/MIT MIT
*/

namespace WordPressCS\WordPress\Helpers;

use PHPCSUtils\Utils\PassedParameters;

/**
* Helper utilities for recognizing functions related to the WP Hook mechanism.
*
* @package WPCS\WordPressCodingStandards
* @since 3.0.0 The property in this class was previously contained in the
* `WordPressCS\WordPress\Sniff` class and has been moved here.
*/
final class WPHookHelper {

/**
* A list of functions that invoke WP hooks (filters/actions).
*
* @since 0.10.0
* @since 0.11.0 Changed from public static to protected non-static.
* @since 3.0.0 - Moved from the Sniff class to this class.
* - The property visibility has changed from `protected` to `private static`.
* Use the `get_function_names()` method for access.
* - The format of the value has changed from a non-relevant boolean to
* an array with the parameter position and name(s) for the hook name parameter.
*
* @var array<string, <string, int|string|array>> Function name as key, array with target
GaryJones marked this conversation as resolved.
Show resolved Hide resolved
* parameter position and name(s) as value.
*/
private static $hookInvokeFunctions = array(
'do_action' => array(
'position' => 1,
'name' => 'hook_name',
GaryJones marked this conversation as resolved.
Show resolved Hide resolved
),
'do_action_ref_array' => array(
'position' => 1,
'name' => 'hook_name',
),
'do_action_deprecated' => array(
'position' => 1,
'name' => 'hook_name',
),
'apply_filters' => array(
'position' => 1,
'name' => 'hook_name',
),
'apply_filters_ref_array' => array(
'position' => 1,
'name' => 'hook_name',
),
'apply_filters_deprecated' => array(
'position' => 1,
'name' => 'hook_name',
),
);

/**
* Retrieve a list of the WordPress functions which invoke hooks.
*
* @since 3.0.0
*
* @param bool $include_deprecated Whether to include the names of functions
* which are used to invoke deprecated hooks.
* Defaults to `true`.
*
* @return array<string, bool> Array with the function names as keys. The value is irrelevant.
*/
public static function get_functions( $include_deprecated = true ) {
$hooks = array_fill_keys( array_keys( self::$hookInvokeFunctions ), true );
if ( false === $include_deprecated ) {
unset(
$hooks['do_action_deprecated'],
$hooks['apply_filters_deprecated']
);
}

return $hooks;
}

/**
* Retrieve the parameter information for the hook name parameter from a stack of parameters
* passed to one of the WP hook functions.
*
* @since 3.0.0
*
* @param string $function_name The name of the WP hook function which the parameters were passed to.
* @param array $parameters The output of a previous call to PassedParameters::getParameters().
*
* @return array|false Array with information on the parameter at the specified offset,
* or with the specified name.
* Or `FALSE` if the specified parameter is not found.
* See the PHPCSUtils PassedParameters::getParameters() documentation
* for the format of the returned (single-dimensional) array.
*/
public static function get_hook_name_param( $function_name, array $parameters ) {
$function_lc = strtolower( $function_name );
if ( isset( self::$hookInvokeFunctions[ $function_lc ] ) === false ) {
return false;
}

return PassedParameters::getParameterFromStack(
$parameters,
self::$hookInvokeFunctions[ $function_lc ]['position'],
self::$hookInvokeFunctions[ $function_lc ]['name']
);
}
}
40 changes: 0 additions & 40 deletions WordPress/Sniff.php
Original file line number Diff line number Diff line change
Expand Up @@ -470,46 +470,6 @@ abstract class Sniff implements PHPCS_Sniff {
'clean_user_cache' => true,
);

/**
* A list of functions that invoke WP hooks (filters/actions).
*
* @since 0.10.0
* @since 0.11.0 Changed from public static to protected non-static.
*
* @var array
*/
protected $hookInvokeFunctions = array(
'do_action' => true,
'do_action_ref_array' => true,
'do_action_deprecated' => true,
'apply_filters' => true,
'apply_filters_ref_array' => true,
'apply_filters_deprecated' => true,
);

/**
* A list of functions that are used to interact with the WP plugins API.
*
* @since 0.10.0
* @since 0.11.0 Changed from public static to protected non-static.
*
* @var array <string function name> => <int position of the hook name argument in function signature>
*/
protected $hookFunctions = array(
'has_filter' => 1,
'add_filter' => 1,
'remove_filter' => 1,
'remove_all_filters' => 1,
'doing_filter' => 1, // Hook name optional.
'has_action' => 1,
'add_action' => 1,
'doing_action' => 1, // Hook name optional.
'did_action' => 1,
'remove_action' => 1,
'remove_all_actions' => 1,
'current_filter' => 0, // No hook name argument.
);

/**
* List of global WP variables.
*
Expand Down
9 changes: 3 additions & 6 deletions WordPress/Sniffs/NamingConventions/PrefixAllGlobalsSniff.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use WordPressCS\WordPress\AbstractFunctionParameterSniff;
use WordPressCS\WordPress\Helpers\DeprecationHelper;
use WordPressCS\WordPress\Helpers\IsUnitTestTrait;
use WordPressCS\WordPress\Helpers\WPHookHelper;

/**
* Verify that everything defined in the global namespace is prefixed with a theme/plugin specific prefix.
Expand Down Expand Up @@ -254,12 +255,8 @@ public function register() {
* @return array
*/
public function getGroups() {
$this->target_functions = $this->hookInvokeFunctions;
unset(
$this->target_functions['do_action_deprecated'],
$this->target_functions['apply_filters_deprecated']
);

// Only retrieve functions which are not used for deprecated hooks.
$this->target_functions = WPHookHelper::get_functions( false );
$this->target_functions['define'] = true;

return parent::getGroups();
Expand Down
12 changes: 4 additions & 8 deletions WordPress/Sniffs/NamingConventions/ValidHookNameSniff.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@

namespace WordPressCS\WordPress\Sniffs\NamingConventions;

use WordPressCS\WordPress\AbstractFunctionParameterSniff;
use PHP_CodeSniffer\Util\Tokens;
use PHPCSUtils\Utils\TextStrings;
use WordPressCS\WordPress\AbstractFunctionParameterSniff;
use WordPressCS\WordPress\Helpers\WPHookHelper;

/**
* Use lowercase letters in action and filter names. Separate words via underscores.
Expand Down Expand Up @@ -73,13 +74,8 @@ class ValidHookNameSniff extends AbstractFunctionParameterSniff {
* @return array
*/
public function getGroups() {
$this->target_functions = $this->hookInvokeFunctions;

// No need to examine the names of deprecated hooks.
unset(
$this->target_functions['do_action_deprecated'],
$this->target_functions['apply_filters_deprecated']
);
// Only retrieve functions which are not used for deprecated hooks.
$this->target_functions = WPHookHelper::get_functions( false );

return parent::getGroups();
}
Expand Down