Skip to content

Commit

Permalink
Merge pull request #1894 from WordPress/develop
Browse files Browse the repository at this point in the history
Release version 2.3.0
  • Loading branch information
jrfnl committed May 13, 2020
2 parents b5a4532 + 1f525cc commit 7da1894
Show file tree
Hide file tree
Showing 19 changed files with 232 additions and 44 deletions.
39 changes: 29 additions & 10 deletions .travis.yml
Expand Up @@ -45,7 +45,7 @@ jobs:
include:
#### SNIFF STAGE ####
- stage: sniff
php: 7.3
php: 7.4
env: PHPCS_BRANCH="dev-master"
addons:
apt:
Expand All @@ -70,12 +70,21 @@ jobs:
- diff -B --tabsize=4 ./WordPress-Extra/ruleset.xml <(xmllint --format "./WordPress-Extra/ruleset.xml")
- diff -B --tabsize=4 ./phpcs.xml.dist.sample <(xmllint --format "./phpcs.xml.dist.sample")

# Validate the composer.json file.
# @link https://getcomposer.org/doc/03-cli.md#validate
- composer validate --no-check-all --strict

# Check that the sniffs available are feature complete.
# For now, just check that all sniffs have unit tests.
# At a later stage the documentation check can be activated.
- composer check-complete

#### RULESET STAGE ####
# Make sure the rulesets don't throw unexpected errors or warnings.
# This check needs to be run against a high PHP version to prevent triggering the syntax error check.
# It also needs to be run against all PHPCS versions WPCS is tested against.
- stage: rulesets
php: 7.3
php: 7.4
env: PHPCS_BRANCH="dev-master"
script:
- $(pwd)/vendor/bin/phpcs -ps ./bin/class-ruleset-test.php --standard=WordPress-Core
Expand All @@ -91,7 +100,7 @@ jobs:
- travis_retry $(pwd)/vendor/bin/phpcbf -pq ./WordPress/Tests/ --standard=WordPress --extensions=inc --exclude=Generic.PHP.Syntax --report=summary

- stage: rulesets
php: 7.3
php: 7.4
env: PHPCS_BRANCH="3.3.1"
script:
- $(pwd)/vendor/bin/phpcs -ps ./bin/class-ruleset-test.php --standard=WordPress-Core
Expand All @@ -103,7 +112,7 @@ jobs:
# This is a much quicker test which only runs the unit tests and linting against the low/high
# supported PHP/PHPCS combinations.
- stage: quicktest
php: 7.3
php: 7.4
env: PHPCS_BRANCH="dev-master" LINT=1
- php: 7.3
env: PHPCS_BRANCH="3.3.1"
Expand All @@ -112,9 +121,16 @@ jobs:
- php: 5.4
env: PHPCS_BRANCH="3.3.1"

#### TEST STAGE ####
# Add extra build to test against PHPCS 4.
- stage: test
php: 7.4
env: PHPCS_BRANCH="4.0.x-dev"

allow_failures:
# Allow failures for unstable builds.
- php: "nightly"
- env: PHPCS_BRANCH="4.0.x-dev"

before_install:
# Speed up build time by disabling Xdebug.
Expand All @@ -125,15 +141,22 @@ before_install:
# On stable PHPCS versions, allow for PHP deprecation notices.
# Unit tests don't need to fail on those for stable releases where those issues won't get fixed anymore.
- |
if [[ "$TRAVIS_BUILD_STAGE_NAME" != "Sniff" && $PHPCS_BRANCH != "dev-master" ]]; then
if [[ "${TRAVIS_BUILD_STAGE_NAME^}" != "Sniff" && $PHPCS_BRANCH != "dev-master" ]]; then
echo 'error_reporting = E_ALL & ~E_DEPRECATED' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
fi
- export XMLLINT_INDENT=" "
- export PHPUNIT_DIR=/tmp/phpunit
- |
if [[ $TRAVIS_PHP_VERSION == "nightly" || $PHPCS_BRANCH == "4.0.x-dev" ]]; then
# Even though we're not doing a dev install, dev requirements are still checked.
# Neither the PHPCS Composer plugin nor PHPCompatibility allows yet for PHPCS 4.x.
# The Composer plugin also doesn't allow for installation on PHP 8.x/nightly.
composer remove --dev dealerdirect/phpcodesniffer-composer-installer phpcompatibility/php-compatibility --no-update --no-scripts
fi
- composer require squizlabs/php_codesniffer:${PHPCS_BRANCH} --update-no-dev --no-suggest --no-scripts
- |
if [[ "$TRAVIS_BUILD_STAGE_NAME" == "Sniff" ]]; then
if [[ "${TRAVIS_BUILD_STAGE_NAME^}" == "Sniff" ]]; then
composer install --dev --no-suggest
# The `dev` required DealerDirect Composer plugin takes care of the installed_paths.
else
Expand All @@ -148,10 +171,6 @@ script:
# Lint the PHP files against parse errors.
- if [[ "$LINT" == "1" ]]; then if find . -path ./vendor -prune -o -path ./bin -prune -o -name "*.php" -exec php -l {} \; | grep "^[Parse error|Fatal error]"; then exit 1; fi; fi

# Validate the composer.json file.
# @link https://getcomposer.org/doc/03-cli.md#validate
- if [[ "$LINT" == "1" ]]; then composer validate --no-check-all --strict; fi

# Run the unit tests.
- |
if [[ ${TRAVIS_PHP_VERSION:0:3} > "7.1" ]]; then
Expand Down
18 changes: 18 additions & 0 deletions CHANGELOG.md
Expand Up @@ -8,6 +8,24 @@ This projects adheres to [Semantic Versioning](https://semver.org/) and [Keep a

_No documentation available about unreleased changes as of yet._

## [2.3.0] - 2020-05-14

### Added
- The `WordPress.WP.I18n` sniff contains a new check for translatable text strings which are wrapped in HTML tags, like `<h1>Translate me</h1>`. Those tags should be moved out of the translatable string.
Note: Translatable strings wrapped in `<a href..>` tags where the URL is intended to be localized will not trigger this check.

### Changed
- The default value for `minimum_supported_wp_version`, as used by a [number of sniffs detecting usage of deprecated WP features](https://github.com/WordPress/WordPress-Coding-Standards/wiki/Customizable-sniff-properties#minimum-wp-version-to-check-for-usage-of-deprecated-functions-classes-and-function-parameters), has been updated to `5.1`.
- The `WordPress.WP.DeprecatedFunctions` sniff will now detect functions deprecated in WP 5.4.
- Improved grammar of an error message in the `WordPress.WP.DiscouragedFunctions` sniff.
- CI: The codebase is now - preliminary - being tested against the PHPCS 4.x development branch.

### Fixed
- All function call detection sniffs: fixed a bug where constants with the same name as one of the targeted functions could inadvertently be recognized as if they were a called function.
- `WordPress.DB.PreparedSQL`: fixed a bug where the sniff would trigger on the namespace separator character `\\`.
- `WordPress.Security.EscapeOutput`: fixed a bug with the variable replacement in one of the error messages.


## [2.2.1] - 2020-02-04

### Added
Expand Down
59 changes: 38 additions & 21 deletions WordPress/AbstractFunctionRestrictionsSniff.php
Expand Up @@ -57,7 +57,7 @@ abstract class AbstractFunctionRestrictionsSniff extends Sniff {
*
* @var string
*/
protected $regex_pattern = '`\b(?:%s)\b`i';
protected $regex_pattern = '`^(?:%s)$`i';

/**
* Cache for the group information.
Expand Down Expand Up @@ -212,35 +212,52 @@ public function process_token( $stackPtr ) {
*/
public function is_targetted_token( $stackPtr ) {

// Exclude function definitions, class methods, and namespaced calls.
if ( \T_STRING === $this->tokens[ $stackPtr ]['code'] ) {
if ( $this->is_class_object_call( $stackPtr ) === true ) {
return false;
}
if ( \T_STRING !== $this->tokens[ $stackPtr ]['code'] ) {
return false;
}

if ( $this->is_token_namespaced( $stackPtr ) === true ) {
return false;
}
// Exclude function definitions, class methods, and namespaced calls.
if ( $this->is_class_object_call( $stackPtr ) === true ) {
return false;
}

$prev = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $stackPtr - 1 ), null, true );
if ( $this->is_token_namespaced( $stackPtr ) === true ) {
return false;
}

if ( false !== $prev ) {
// Skip sniffing if calling a same-named method, or on function definitions.
$skipped = array(
\T_FUNCTION => \T_FUNCTION,
\T_CLASS => \T_CLASS,
\T_AS => \T_AS, // Use declaration alias.
);
$prev = $this->phpcsFile->findPrevious( Tokens::$emptyTokens, ( $stackPtr - 1 ), null, true );
if ( false !== $prev ) {
// Skip sniffing on function, class definitions or for function aliases in use statements.
$skipped = array(
\T_FUNCTION => \T_FUNCTION,
\T_CLASS => \T_CLASS,
\T_AS => \T_AS, // Use declaration alias.
);

if ( isset( $skipped[ $this->tokens[ $prev ]['code'] ] ) ) {
return false;
}
if ( isset( $skipped[ $this->tokens[ $prev ]['code'] ] ) ) {
return false;
}
}

// Check if this could even be a function call.
$next = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true );
if ( false === $next ) {
return false;
}

// Check for `use function ... (as|;)`.
if ( ( \T_STRING === $this->tokens[ $prev ]['code'] && 'function' === $this->tokens[ $prev ]['content'] )
&& ( \T_AS === $this->tokens[ $next ]['code'] || \T_SEMICOLON === $this->tokens[ $next ]['code'] )
) {
return true;
}

return false;
// If it's not a `use` statement, there should be parenthesis.
if ( \T_OPEN_PARENTHESIS !== $this->tokens[ $next ]['code'] ) {
return false;
}

return true;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion WordPress/Sniff.php
Expand Up @@ -82,7 +82,7 @@ abstract class Sniff implements PHPCS_Sniff {
*
* @var string WordPress version.
*/
public $minimum_supported_version = '5.0';
public $minimum_supported_version = '5.1';

/**
* Custom list of classes which test classes can extend.
Expand Down
1 change: 1 addition & 0 deletions WordPress/Sniffs/DB/PreparedSQLSniff.php
Expand Up @@ -69,6 +69,7 @@ class PreparedSQLSniff extends Sniff {
\T_INT_CAST => true,
\T_DOUBLE_CAST => true,
\T_BOOL_CAST => true,
\T_NS_SEPARATOR => true,
);

/**
Expand Down
2 changes: 1 addition & 1 deletion WordPress/Sniffs/Security/EscapeOutputSniff.php
Expand Up @@ -456,7 +456,7 @@ public function process_token( $stackPtr ) {
"All output should be run through an escaping function (see the Security sections in the WordPress Developer Handbooks), found '%s'.",
$ptr,
'OutputNotEscaped',
$content
array( $content )
);
}

Expand Down
7 changes: 3 additions & 4 deletions WordPress/Sniffs/WP/AlternativeFunctionsSniff.php
Expand Up @@ -89,6 +89,9 @@ public function getGroups() {
'functions' => array(
'curl_*',
),
'whitelist' => array(
'curl_version' => true,
),
),

'parse_url' => array(
Expand Down Expand Up @@ -273,10 +276,6 @@ public function process_matched_token( $stackPtr, $group_name, $matched_content
unset( $first_param );

break;

case 'curl_version':
// Curl version doesn't actually create a connection.
return;
}

if ( ! isset( $this->groups[ $group_name ]['since'] ) ) {
Expand Down
6 changes: 6 additions & 0 deletions WordPress/Sniffs/WP/DeprecatedFunctionsSniff.php
Expand Up @@ -1359,6 +1359,12 @@ class DeprecatedFunctionsSniff extends AbstractFunctionRestrictionsSniff {
'alt' => 'wp_update_user()',
'version' => '5.3.0',
),

// WP 5.4.0.
'wp_get_user_request_data' => array(
'alt' => 'wp_get_user_request()',
'version' => '5.4.0',
),
);

/**
Expand Down
2 changes: 1 addition & 1 deletion WordPress/Sniffs/WP/DiscouragedFunctionsSniff.php
Expand Up @@ -46,7 +46,7 @@ public function getGroups() {

'wp_reset_query' => array(
'type' => 'warning',
'message' => '%s() is discouraged. Use the wp_reset_postdata() instead.',
'message' => '%s() is discouraged. Use wp_reset_postdata() instead.',
'functions' => array(
'wp_reset_query',
),
Expand Down
39 changes: 37 additions & 2 deletions WordPress/Sniffs/WP/I18nSniff.php
Expand Up @@ -630,11 +630,46 @@ protected function check_text( $context ) {
*
* Strip placeholders and surrounding quotes.
*/
$non_placeholder_content = trim( $this->strip_quotes( $content ) );
$non_placeholder_content = preg_replace( self::SPRINTF_PLACEHOLDER_REGEX, '', $non_placeholder_content );
$content_without_quotes = trim( $this->strip_quotes( $content ) );
$non_placeholder_content = preg_replace( self::SPRINTF_PLACEHOLDER_REGEX, '', $content_without_quotes );

if ( '' === $non_placeholder_content ) {
$this->phpcsFile->addError( 'Strings should have translatable content', $stack_ptr, 'NoEmptyStrings' );
return;
}

/*
* NoHtmlWrappedStrings
*
* Strip surrounding quotes.
*/
$reader = new \XMLReader();
$reader->XML( $content_without_quotes, 'UTF-8', LIBXML_NOERROR | LIBXML_ERR_NONE | LIBXML_NOWARNING );

// Is the first node an HTML element?
if ( ! $reader->read() || \XMLReader::ELEMENT !== $reader->nodeType ) {
return;
}

// If the opening HTML element includes placeholders in its attributes, we don't warn.
// E.g. '<option id="%1$s" value="%2$s">Translatable option name</option>'.
$i = 0;
while ( $attr = $reader->getAttributeNo( $i ) ) {
if ( preg_match( self::SPRINTF_PLACEHOLDER_REGEX, $attr ) === 1 ) {
return;
}

++$i;
}

// We don't flag strings wrapped in `<a href="...">...</a>`, as the link target might actually need localization.
if ( 'a' === $reader->name && $reader->getAttribute( 'href' ) ) {
return;
}

// Does the entire string only consist of this HTML node?
if ( $reader->readOuterXml() === $content_without_quotes ) {
$this->phpcsFile->addWarning( 'Strings should not be wrapped in HTML', $stack_ptr, 'NoHtmlWrappedStrings' );
}
}

Expand Down
2 changes: 1 addition & 1 deletion WordPress/Tests/DB/PreparedSQLUnitTest.inc
Expand Up @@ -39,7 +39,7 @@ $all_post_meta = $wpdb->get_results( $wpdb->prepare( sprintf(
WHERE `meta_key` = "sort_order"
AND `post_id` IN (%s)',
$wpdb->postmeta,
implode( ',', array_fill( 0, count( $post_ids ), '%d' ) )
\implode( ',', \array_fill( 0, \count( $post_ids ), '%d' ) )
), $post_ids ) ); // Ok.

$wpdb->query( "
Expand Down
7 changes: 7 additions & 0 deletions WordPress/Tests/WP/AlternativeFunctionsUnitTest.inc
Expand Up @@ -71,3 +71,10 @@ curl_version(); // OK.

// Safeguard that additional logic uses case-insensitive function name check.
Strip_Tags( $something ); // Warning.

if ( ! $curl['features'] && CURL_VERSION_SSL ) {} // OK.
my_parse_url_function(); // OK.
function curl_version_ssl() {} // OK.
use function curl_version; // OK.
use function something as curl_version; // OK.
use function curl_init as curl_version; // Bad.
1 change: 1 addition & 0 deletions WordPress/Tests/WP/AlternativeFunctionsUnitTest.php
Expand Up @@ -64,6 +64,7 @@ public function getWarningList() {
67 => 1,
68 => 1,
73 => 1,
80 => 1,
);
}

Expand Down
2 changes: 2 additions & 0 deletions WordPress/Tests/WP/DeprecatedFunctionsUnitTest.inc
Expand Up @@ -345,3 +345,5 @@ install_blog();
_wp_json_prepare_data();
_wp_privacy_requests_screen_options();
update_user_status();
/* ============ WP 5.4 ============ */
wp_get_user_request_data();
7 changes: 5 additions & 2 deletions WordPress/Tests/WP/DeprecatedFunctionsUnitTest.php
Expand Up @@ -76,10 +76,13 @@ public function getErrorList() {
*/
public function getWarningList() {

$warnings = array_fill( 342, 6, 1 );
$warnings = array_fill( 342, 8, 1 );

// Unset the lines related to version comments.
unset( $warnings[344] );
unset(
$warnings[344],
$warnings[348]
);

return $warnings;
}
Expand Down

0 comments on commit 7da1894

Please sign in to comment.