Skip to content

Commit

Permalink
WP/PostsPerPage: allow for non-decimal nrs, PHP 7.4 numeric literals,…
Browse files Browse the repository at this point in the history
… PHP 8.1 octal literals

While it will probably be exceedingly rare for the `posts_per_page` value to be passed as anything but a decimal number (except to bypass the sniff), the sniff should still treat numbers passed using a different base correctly.

Along the same lines, decimal numbers passed using PHP 7.4 numeric literal notation should also be handled correctly.

Fixed now. Includes safeguard to only handle text string values when they are purely numeric.

Includes tests.
  • Loading branch information
jrfnl committed Jul 4, 2023
1 parent 0ececb6 commit 5cf4fe1
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 3 deletions.
29 changes: 26 additions & 3 deletions WordPress/Sniffs/WP/PostsPerPageSniff.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

namespace WordPressCS\WordPress\Sniffs\WP;

use PHPCSUtils\Utils\Numbers;
use PHPCSUtils\Utils\TextStrings;
use WordPressCS\WordPress\AbstractArrayAssignmentRestrictionsSniff;

Expand Down Expand Up @@ -68,12 +69,34 @@ public function getGroups() {
* @return bool FALSE if no match, TRUE if matches.
*/
public function callback( $key, $val, $line, $group ) {
$val = TextStrings::stripQuotes( $val );
if ( preg_match( '`^[+-]?[0-9]+$`', $val ) !== 1 ) {
// Not a purely numeric value, so any comparison would be a false comparison.
$stripped_val = TextStrings::stripQuotes( $val );

if ( $val !== $stripped_val ) {
// The value was a text string. For text strings, we only accept purely numeric values.
if ( preg_match( '`^[0-9]+$`', $stripped_val ) !== 1 ) {
// Not a purely numeric value, so any comparison would be a false comparison.
return false;
}

// Purely numeric string, treat it as an integer from here on out.
$val = $stripped_val;
}

$first_char = $val[0];
if ( '-' === $first_char || '+' === $first_char ) {
$val = ltrim( $val, '-+' );
} else {
$first_char = '';
}

$real_value = Numbers::getDecimalValue( $val );
if ( false === $real_value ) {
// This wasn't a purely numeric value, so any comparison would be a false comparison.
return false;
}

$val = $first_char . $real_value;

return ( (int) $val > (int) $this->posts_per_page );
}
}
16 changes: 16 additions & 0 deletions WordPress/Tests/WP/PostsPerPageUnitTest.inc
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,19 @@ $args = array(
'posts_per_page' => +50, // OK.
'posts_per_page' => +200, // Bad.
);

// Verify handling of PHP 7.4+ numeric literals, PHP 8.1 octal literals, non-decimal numbers and floats.
$args = array(
'posts_per_page' => 0b1001011, // OK (75).
'posts_per_page' => 0b10010110, // Bad (150).
'posts_per_page' => 0x4B, // OK (75).
'posts_per_page' => 0x96, // Bad (150).
'posts_per_page' => 0113, // OK (75).
'posts_per_page' => 0226, // Bad (150).
'posts_per_page' => 0O113, // OK (75).
'posts_per_page' => 0o226, // Bad (150).
'posts_per_page' => 7_5, // OK (75).
'posts_per_page' => 1_50, // Bad (150).
'posts_per_page' => 75.0, // OK (75).
'posts_per_page' => 150.000, // Bad (150).
);
6 changes: 6 additions & 0 deletions WordPress/Tests/WP/PostsPerPageUnitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ public function getWarningList() {
103 => 1,
104 => 1,
109 => 1,
115 => 1,
117 => 1,
119 => 1,
121 => 1,
123 => 1,
125 => 1,
);
}
}

0 comments on commit 5cf4fe1

Please sign in to comment.