Skip to content

Commit 7da1894

Browse files
authored
Merge pull request #1894 from WordPress/develop
Release version 2.3.0
2 parents b5a4532 + 1f525cc commit 7da1894

19 files changed

+232
-44
lines changed

.travis.yml

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ jobs:
4545
include:
4646
#### SNIFF STAGE ####
4747
- stage: sniff
48-
php: 7.3
48+
php: 7.4
4949
env: PHPCS_BRANCH="dev-master"
5050
addons:
5151
apt:
@@ -70,12 +70,21 @@ jobs:
7070
- diff -B --tabsize=4 ./WordPress-Extra/ruleset.xml <(xmllint --format "./WordPress-Extra/ruleset.xml")
7171
- diff -B --tabsize=4 ./phpcs.xml.dist.sample <(xmllint --format "./phpcs.xml.dist.sample")
7272

73+
# Validate the composer.json file.
74+
# @link https://getcomposer.org/doc/03-cli.md#validate
75+
- composer validate --no-check-all --strict
76+
77+
# Check that the sniffs available are feature complete.
78+
# For now, just check that all sniffs have unit tests.
79+
# At a later stage the documentation check can be activated.
80+
- composer check-complete
81+
7382
#### RULESET STAGE ####
7483
# Make sure the rulesets don't throw unexpected errors or warnings.
7584
# This check needs to be run against a high PHP version to prevent triggering the syntax error check.
7685
# It also needs to be run against all PHPCS versions WPCS is tested against.
7786
- stage: rulesets
78-
php: 7.3
87+
php: 7.4
7988
env: PHPCS_BRANCH="dev-master"
8089
script:
8190
- $(pwd)/vendor/bin/phpcs -ps ./bin/class-ruleset-test.php --standard=WordPress-Core
@@ -91,7 +100,7 @@ jobs:
91100
- travis_retry $(pwd)/vendor/bin/phpcbf -pq ./WordPress/Tests/ --standard=WordPress --extensions=inc --exclude=Generic.PHP.Syntax --report=summary
92101

93102
- stage: rulesets
94-
php: 7.3
103+
php: 7.4
95104
env: PHPCS_BRANCH="3.3.1"
96105
script:
97106
- $(pwd)/vendor/bin/phpcs -ps ./bin/class-ruleset-test.php --standard=WordPress-Core
@@ -103,7 +112,7 @@ jobs:
103112
# This is a much quicker test which only runs the unit tests and linting against the low/high
104113
# supported PHP/PHPCS combinations.
105114
- stage: quicktest
106-
php: 7.3
115+
php: 7.4
107116
env: PHPCS_BRANCH="dev-master" LINT=1
108117
- php: 7.3
109118
env: PHPCS_BRANCH="3.3.1"
@@ -112,9 +121,16 @@ jobs:
112121
- php: 5.4
113122
env: PHPCS_BRANCH="3.3.1"
114123

124+
#### TEST STAGE ####
125+
# Add extra build to test against PHPCS 4.
126+
- stage: test
127+
php: 7.4
128+
env: PHPCS_BRANCH="4.0.x-dev"
129+
115130
allow_failures:
116131
# Allow failures for unstable builds.
117132
- php: "nightly"
133+
- env: PHPCS_BRANCH="4.0.x-dev"
118134

119135
before_install:
120136
# Speed up build time by disabling Xdebug.
@@ -125,15 +141,22 @@ before_install:
125141
# On stable PHPCS versions, allow for PHP deprecation notices.
126142
# Unit tests don't need to fail on those for stable releases where those issues won't get fixed anymore.
127143
- |
128-
if [[ "$TRAVIS_BUILD_STAGE_NAME" != "Sniff" && $PHPCS_BRANCH != "dev-master" ]]; then
144+
if [[ "${TRAVIS_BUILD_STAGE_NAME^}" != "Sniff" && $PHPCS_BRANCH != "dev-master" ]]; then
129145
echo 'error_reporting = E_ALL & ~E_DEPRECATED' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
130146
fi
131147
132148
- export XMLLINT_INDENT=" "
133149
- export PHPUNIT_DIR=/tmp/phpunit
150+
- |
151+
if [[ $TRAVIS_PHP_VERSION == "nightly" || $PHPCS_BRANCH == "4.0.x-dev" ]]; then
152+
# Even though we're not doing a dev install, dev requirements are still checked.
153+
# Neither the PHPCS Composer plugin nor PHPCompatibility allows yet for PHPCS 4.x.
154+
# The Composer plugin also doesn't allow for installation on PHP 8.x/nightly.
155+
composer remove --dev dealerdirect/phpcodesniffer-composer-installer phpcompatibility/php-compatibility --no-update --no-scripts
156+
fi
134157
- composer require squizlabs/php_codesniffer:${PHPCS_BRANCH} --update-no-dev --no-suggest --no-scripts
135158
- |
136-
if [[ "$TRAVIS_BUILD_STAGE_NAME" == "Sniff" ]]; then
159+
if [[ "${TRAVIS_BUILD_STAGE_NAME^}" == "Sniff" ]]; then
137160
composer install --dev --no-suggest
138161
# The `dev` required DealerDirect Composer plugin takes care of the installed_paths.
139162
else
@@ -148,10 +171,6 @@ script:
148171
# Lint the PHP files against parse errors.
149172
- 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
150173

151-
# Validate the composer.json file.
152-
# @link https://getcomposer.org/doc/03-cli.md#validate
153-
- if [[ "$LINT" == "1" ]]; then composer validate --no-check-all --strict; fi
154-
155174
# Run the unit tests.
156175
- |
157176
if [[ ${TRAVIS_PHP_VERSION:0:3} > "7.1" ]]; then

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,24 @@ This projects adheres to [Semantic Versioning](https://semver.org/) and [Keep a
88

99
_No documentation available about unreleased changes as of yet._
1010

11+
## [2.3.0] - 2020-05-14
12+
13+
### Added
14+
- 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.
15+
Note: Translatable strings wrapped in `<a href..>` tags where the URL is intended to be localized will not trigger this check.
16+
17+
### Changed
18+
- 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`.
19+
- The `WordPress.WP.DeprecatedFunctions` sniff will now detect functions deprecated in WP 5.4.
20+
- Improved grammar of an error message in the `WordPress.WP.DiscouragedFunctions` sniff.
21+
- CI: The codebase is now - preliminary - being tested against the PHPCS 4.x development branch.
22+
23+
### Fixed
24+
- 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.
25+
- `WordPress.DB.PreparedSQL`: fixed a bug where the sniff would trigger on the namespace separator character `\\`.
26+
- `WordPress.Security.EscapeOutput`: fixed a bug with the variable replacement in one of the error messages.
27+
28+
1129
## [2.2.1] - 2020-02-04
1230

1331
### Added

WordPress/AbstractFunctionRestrictionsSniff.php

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ abstract class AbstractFunctionRestrictionsSniff extends Sniff {
5757
*
5858
* @var string
5959
*/
60-
protected $regex_pattern = '`\b(?:%s)\b`i';
60+
protected $regex_pattern = '`^(?:%s)$`i';
6161

6262
/**
6363
* Cache for the group information.
@@ -212,35 +212,52 @@ public function process_token( $stackPtr ) {
212212
*/
213213
public function is_targetted_token( $stackPtr ) {
214214

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

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

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

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

235-
if ( isset( $skipped[ $this->tokens[ $prev ]['code'] ] ) ) {
236-
return false;
237-
}
237+
if ( isset( $skipped[ $this->tokens[ $prev ]['code'] ] ) ) {
238+
return false;
238239
}
240+
}
241+
242+
// Check if this could even be a function call.
243+
$next = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true );
244+
if ( false === $next ) {
245+
return false;
246+
}
239247

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

243-
return false;
255+
// If it's not a `use` statement, there should be parenthesis.
256+
if ( \T_OPEN_PARENTHESIS !== $this->tokens[ $next ]['code'] ) {
257+
return false;
258+
}
259+
260+
return true;
244261
}
245262

246263
/**

WordPress/Sniff.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ abstract class Sniff implements PHPCS_Sniff {
8282
*
8383
* @var string WordPress version.
8484
*/
85-
public $minimum_supported_version = '5.0';
85+
public $minimum_supported_version = '5.1';
8686

8787
/**
8888
* Custom list of classes which test classes can extend.

WordPress/Sniffs/DB/PreparedSQLSniff.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class PreparedSQLSniff extends Sniff {
6969
\T_INT_CAST => true,
7070
\T_DOUBLE_CAST => true,
7171
\T_BOOL_CAST => true,
72+
\T_NS_SEPARATOR => true,
7273
);
7374

7475
/**

WordPress/Sniffs/Security/EscapeOutputSniff.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ public function process_token( $stackPtr ) {
456456
"All output should be run through an escaping function (see the Security sections in the WordPress Developer Handbooks), found '%s'.",
457457
$ptr,
458458
'OutputNotEscaped',
459-
$content
459+
array( $content )
460460
);
461461
}
462462

WordPress/Sniffs/WP/AlternativeFunctionsSniff.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ public function getGroups() {
8989
'functions' => array(
9090
'curl_*',
9191
),
92+
'whitelist' => array(
93+
'curl_version' => true,
94+
),
9295
),
9396

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

275278
break;
276-
277-
case 'curl_version':
278-
// Curl version doesn't actually create a connection.
279-
return;
280279
}
281280

282281
if ( ! isset( $this->groups[ $group_name ]['since'] ) ) {

WordPress/Sniffs/WP/DeprecatedFunctionsSniff.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,6 +1359,12 @@ class DeprecatedFunctionsSniff extends AbstractFunctionRestrictionsSniff {
13591359
'alt' => 'wp_update_user()',
13601360
'version' => '5.3.0',
13611361
),
1362+
1363+
// WP 5.4.0.
1364+
'wp_get_user_request_data' => array(
1365+
'alt' => 'wp_get_user_request()',
1366+
'version' => '5.4.0',
1367+
),
13621368
);
13631369

13641370
/**

WordPress/Sniffs/WP/DiscouragedFunctionsSniff.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public function getGroups() {
4646

4747
'wp_reset_query' => array(
4848
'type' => 'warning',
49-
'message' => '%s() is discouraged. Use the wp_reset_postdata() instead.',
49+
'message' => '%s() is discouraged. Use wp_reset_postdata() instead.',
5050
'functions' => array(
5151
'wp_reset_query',
5252
),

WordPress/Sniffs/WP/I18nSniff.php

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -630,11 +630,46 @@ protected function check_text( $context ) {
630630
*
631631
* Strip placeholders and surrounding quotes.
632632
*/
633-
$non_placeholder_content = trim( $this->strip_quotes( $content ) );
634-
$non_placeholder_content = preg_replace( self::SPRINTF_PLACEHOLDER_REGEX, '', $non_placeholder_content );
633+
$content_without_quotes = trim( $this->strip_quotes( $content ) );
634+
$non_placeholder_content = preg_replace( self::SPRINTF_PLACEHOLDER_REGEX, '', $content_without_quotes );
635635

636636
if ( '' === $non_placeholder_content ) {
637637
$this->phpcsFile->addError( 'Strings should have translatable content', $stack_ptr, 'NoEmptyStrings' );
638+
return;
639+
}
640+
641+
/*
642+
* NoHtmlWrappedStrings
643+
*
644+
* Strip surrounding quotes.
645+
*/
646+
$reader = new \XMLReader();
647+
$reader->XML( $content_without_quotes, 'UTF-8', LIBXML_NOERROR | LIBXML_ERR_NONE | LIBXML_NOWARNING );
648+
649+
// Is the first node an HTML element?
650+
if ( ! $reader->read() || \XMLReader::ELEMENT !== $reader->nodeType ) {
651+
return;
652+
}
653+
654+
// If the opening HTML element includes placeholders in its attributes, we don't warn.
655+
// E.g. '<option id="%1$s" value="%2$s">Translatable option name</option>'.
656+
$i = 0;
657+
while ( $attr = $reader->getAttributeNo( $i ) ) {
658+
if ( preg_match( self::SPRINTF_PLACEHOLDER_REGEX, $attr ) === 1 ) {
659+
return;
660+
}
661+
662+
++$i;
663+
}
664+
665+
// We don't flag strings wrapped in `<a href="...">...</a>`, as the link target might actually need localization.
666+
if ( 'a' === $reader->name && $reader->getAttribute( 'href' ) ) {
667+
return;
668+
}
669+
670+
// Does the entire string only consist of this HTML node?
671+
if ( $reader->readOuterXml() === $content_without_quotes ) {
672+
$this->phpcsFile->addWarning( 'Strings should not be wrapped in HTML', $stack_ptr, 'NoHtmlWrappedStrings' );
638673
}
639674
}
640675

0 commit comments

Comments
 (0)