Skip to content

Commit

Permalink
Create the HookPriorityLimit Sniff (#75)
Browse files Browse the repository at this point in the history
* Create the HookPriorityLimit Sniff

It checks if `PHP_INT_MAX` or `PHP_INT_MIN` are added used for `add_filter` or `add_action`.

* Convert errors to warnings

* Update documentation

* Rename the sniff in `HookPrioritySniff`

* Simplify the code

Use the utility method `PassedParameters::getParameter()` in order to get rid of a lot of custom code.

* Update the sniff name in the readme
  • Loading branch information
antonioeatgoat authored Oct 27, 2023
1 parent ecb838a commit 6edffc8
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 0 deletions.
85 changes: 85 additions & 0 deletions Inpsyde/Sniffs/CodeQuality/HookPrioritySniff.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php

/*
* This file is part of the "php-coding-standards" package.
*
* Copyright (c) 2023 Inpsyde GmbH
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

declare(strict_types=1);

namespace Inpsyde\Sniffs\CodeQuality;

use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHPCSUtils\Utils\PassedParameters;

class HookPrioritySniff implements Sniff
{
/**
* @return list<int>
*/
public function register(): array
{
return [T_STRING];
}

/**
* @param File $phpcsFile
* @param int $stackPtr
* @return void
*
* phpcs:disable Inpsyde.CodeQuality.ArgumentTypeDeclaration
*/
public function process(File $phpcsFile, $stackPtr): void
{
// phpcs:enable Inpsyde.CodeQuality.ArgumentTypeDeclaration

$tokens = $phpcsFile->getTokens();
$functionName = $tokens[$stackPtr]['content'] ?? '';

if ($functionName !== 'add_filter' && $functionName !== 'add_action') {
return;
}

$parameter = PassedParameters::getParameter($phpcsFile, $stackPtr, 3, 'priority');
$parameter = $parameter['clean'] ?? '';

if ($parameter === 'PHP_INT_MAX' && $functionName === 'add_filter') {
$phpcsFile->addWarning(
'Found PHP_INT_MAX used as hook priority. '
. 'This makes it hard, if not impossible to reliably filter the callback output.',
$stackPtr,
'HookPriority'
);
return;
}

if ($parameter === 'PHP_INT_MIN') {
$phpcsFile->addWarning(
'Found PHP_INT_MIN used as hook priority. '
. 'This makes it hard, if not impossible to reliably remove the callback.',
$stackPtr,
'HookPriority'
);
}
}
}
7 changes: 7 additions & 0 deletions inpsyde-custom-sniffs.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,13 @@ Analyses closures attached to WordPress hooks ensuring that:

This sniff has no available configuration.

-----
## Inpsyde.CodeQuality.HookPriority

Raises a warning if:

- `PHP_INT_MAX` is used for `add_filter`.
- `PHP_INT_MIN` is used for `add_action` or `add_filter`.
-----

## Inpsyde.CodeQuality.LineLength
Expand Down
92 changes: 92 additions & 0 deletions tests/fixtures/hook-priority.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php

namespace Inpsyde\CodingStandard\Tests\Fixtures;

// @phpcsSniff CodeQuality.HookPriority
add_action('foo', 'bar');

add_filter('foo', [ArrayObject::class, 'meh']);

add_filter(
'foo',
function() {
return true;
}
);

add_action(
'hook',
function() {
echo 'hello';
}
);

add_action('foo', 'bar', 10);
add_action('foo', [ArrayObject::class, 'meh'], -500);

add_filter('foo', 'bar', 500);
add_filter('foo', [ArrayObject::class, 'meh'], 20);

add_filter(
'foo',
function() {
return true;
},
-500
);

add_action(
'hook',
function() {
echo 'hello';
},
9999
);

// @phpcsWarningCodeOnNextLine HookPriority
add_filter('foo', 'foo', PHP_INT_MIN);
// @phpcsWarningCodeOnNextLine HookPriority
add_filter('foo', [ArrayObject::class, 'meh'], PHP_INT_MIN);
// @phpcsWarningCodeOnNextLine HookPriority
add_filter(
'foo',
function() {
return true;
},
PHP_INT_MIN
);

// @phpcsWarningCodeOnNextLine HookPriority
add_action('foo', 'foo', PHP_INT_MIN);
// @phpcsWarningCodeOnNextLine HookPriority
add_action('foo', [ArrayObject::class, 'meh'], PHP_INT_MIN);
// @phpcsWarningCodeOnNextLine HookPriority
add_action(
'hook',
function() {
echo 'hello';
},
PHP_INT_MIN
);

// @phpcsWarningCodeOnNextLine HookPriority
add_filter('foo', 'foo', PHP_INT_MAX);
// @phpcsWarningCodeOnNextLine HookPriority
add_filter('foo', [ArrayObject::class, 'meh'], PHP_INT_MAX);
// @phpcsWarningCodeOnNextLine HookPriority
add_filter('foo',
function() {
return true;
},
PHP_INT_MAX
);

add_action('foo', 'foo', PHP_INT_MAX);
add_action('foo', [ArrayObject::class, 'meh'], PHP_INT_MAX);
add_action(
'foo',
function() {
return true;
},
PHP_INT_MAX
);

0 comments on commit 6edffc8

Please sign in to comment.