Skip to content

Commit be9f57d

Browse files
committed
I18n: bug fix - trying to access array offset on null (PHP 7.4)
When a function call to one of the singular/plural text translation functions - like `_n_noop()` - is missing an argument, the sniff would still try an execute the `compare_single_and_plural_arguments()` check and on PHP 7.4 would generate a "Trying to access array offset on value of type null" error which would stop the PHPCS run dead with an `Internal.Exception` error code. Fixed by skipping the check in that case. The missing argument should be reported by the preceding `check_argument_tokens()` check anyhow. Includes unit test.
1 parent 87c6153 commit be9f57d

File tree

4 files changed

+24
-2
lines changed

4 files changed

+24
-2
lines changed

WordPress/Sniffs/WP/I18nSniff.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -390,8 +390,16 @@ public function process_matched_token( $stack_ptr, $group_name, $matched_content
390390
$this->check_argument_tokens( $argument_assertion_context );
391391
}
392392

393-
// For _n*() calls, compare the singular and plural strings.
394-
if ( false !== strpos( $this->i18n_functions[ $matched_content ], 'number' ) ) {
393+
/*
394+
* For _n*() calls, compare the singular and plural strings.
395+
* If either of the arguments is missing, empty or has more than 1 token, skip out.
396+
* An error for that will already have been reported via the `check_argument_tokens()` method.
397+
*/
398+
if ( false !== strpos( $this->i18n_functions[ $matched_content ], 'number' )
399+
&& isset( $argument_assertions[0]['tokens'], $argument_assertions[1]['tokens'] )
400+
&& count( $argument_assertions[0]['tokens'] ) === 1
401+
&& count( $argument_assertions[1]['tokens'] ) === 1
402+
) {
395403
$single_context = $argument_assertions[0];
396404
$plural_context = $argument_assertions[1];
397405

WordPress/Tests/WP/I18nUnitTest.1.inc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,5 +177,11 @@ $offset_or_tz = _x( '0', 'default GMT offset or timezone string', 'my-slug' );
177177
$test = __( '%1$s %2$s', 'my-slug' ); // OK(ish), placeholder order may change depending on language.
178178
$test = __( ' %s ', 'my-slug' ); // Bad, no translatable content.
179179

180+
// Missing plural argument.
181+
_n_noop($singular); // Bad x 3.
182+
183+
// This test is needed to verify that the missing plural argument above does not cause an internal error, stopping the run.
184+
_n_noop( 'I have %d cat.', 'I have %d cats.' ); // Bad.
185+
180186
// phpcs:set WordPress.WP.I18n text_domain[]
181187
// phpcs:set WordPress.WP.I18n check_translator_comments true

WordPress/Tests/WP/I18nUnitTest.1.inc.fixed

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,5 +177,11 @@ $offset_or_tz = _x( '0', 'default GMT offset or timezone string', 'my-slug' );
177177
$test = __( '%1$s %2$s', 'my-slug' ); // OK(ish), placeholder order may change depending on language.
178178
$test = __( ' %s ', 'my-slug' ); // Bad, no translatable content.
179179

180+
// Missing plural argument.
181+
_n_noop($singular); // Bad x 3.
182+
183+
// This test is needed to verify that the missing plural argument above does not cause an internal error, stopping the run.
184+
_n_noop( 'I have %d cat.', 'I have %d cats.' ); // Bad.
185+
180186
// phpcs:set WordPress.WP.I18n text_domain[]
181187
// phpcs:set WordPress.WP.I18n check_translator_comments true

WordPress/Tests/WP/I18nUnitTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ public function getErrorList( $testFile = '' ) {
114114
153 => 1,
115115
157 => 1,
116116
178 => 1,
117+
181 => 3,
118+
184 => 1,
117119
);
118120

119121
case 'I18nUnitTest.2.inc':

0 commit comments

Comments
 (0)