Skip to content

Commit

Permalink
New "DateTime.RestrictedFunctions" sniff (#1807)
Browse files Browse the repository at this point in the history
New "DateTime.RestrictedFunctions" sniff
  • Loading branch information
GaryJones authored Oct 27, 2019
2 parents fcaf02b + 7947bce commit 619ced0
Show file tree
Hide file tree
Showing 12 changed files with 187 additions and 36 deletions.
4 changes: 4 additions & 0 deletions WordPress-Core/ruleset.xml
Original file line number Diff line number Diff line change
Expand Up @@ -519,4 +519,8 @@
<!-- Check for correct spelling of WordPress. -->
<rule ref="WordPress.WP.CapitalPDangit"/>

<!-- Use the appropriate DateTime functions.
See: https://github.com/WordPress/WordPress-Coding-Standards/issues/1713 -->
<rule ref="WordPress.DateTime.RestrictedFunctions"/>

</ruleset>
1 change: 0 additions & 1 deletion WordPress-Extra/ruleset.xml
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@
<rule ref="WordPress.Security.PluginMenuSlug"/>
<rule ref="WordPress.WP.CronInterval"/>
<rule ref="WordPress.WP.PostsPerPage"/>
<rule ref="WordPress.WP.TimezoneChange"/>

<!-- Verify some regex best practices.
https://github.com/WordPress/WordPress-Coding-Standards/issues/1371 -->
Expand Down
62 changes: 62 additions & 0 deletions WordPress/Sniffs/DateTime/RestrictedFunctionsSniff.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php
/**
* WordPress Coding Standard.
*
* @package WPCS\WordPressCodingStandards
* @link https://github.com/WordPress/WordPress-Coding-Standards
* @license https://opensource.org/licenses/MIT MIT
*/

namespace WordPressCS\WordPress\Sniffs\DateTime;

use WordPressCS\WordPress\AbstractFunctionRestrictionsSniff;

/**
* Forbids the use of various native DateTime related PHP/WP functions and suggests alternatives.
*
* @package WPCS\WordPressCodingStandards
*
* @since 2.2.0
*/
class RestrictedFunctionsSniff extends AbstractFunctionRestrictionsSniff {

/**
* Groups of functions to restrict.
*
* @return array
*/
public function getGroups() {
return array(

/*
* Disallow the changing the timezone.
*
* @link https://vip.wordpress.com/documentation/vip-go/code-review-blockers-warnings-notices/#manipulating-the-timezone-server-side
*/
'timezone_change' => array(
'type' => 'error',
'message' => 'Using %s() and similar isn\'t allowed, instead use WP internal timezone support.',
'functions' => array(
'date_default_timezone_set',
),
),

/*
* Use gmdate(), not date().
* Don't rely on the current PHP time zone as it might have been changed by third party code.
*
* @link https://make.wordpress.org/core/2019/09/23/date-time-improvements-wp-5-3/
* @link https://core.trac.wordpress.org/ticket/46438
* @link https://github.com/WordPress/WordPress-Coding-Standards/issues/1713
*/
'date' => array(
'type' => 'error',
'message' => '%s() is affected by runtime timezone changes which can cause date/time to be incorrectly displayed. Use gmdate() instead.',
'functions' => array(
'date',
),
),
);
}

}
8 changes: 0 additions & 8 deletions WordPress/Sniffs/PHP/RestrictedPHPFunctionsSniff.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
* @package WPCS\WordPressCodingStandards
*
* @since 0.14.0
* @since 2.2.0 New group `date` added.
*/
class RestrictedPHPFunctionsSniff extends AbstractFunctionRestrictionsSniff {

Expand All @@ -43,13 +42,6 @@ public function getGroups() {
'create_function',
),
),
'date' => array(
'type' => 'error',
'message' => '%s() is affected by runtime timezone changes which can cause date/time to be incorrectly displayed. Use gmdate() instead.',
'functions' => array(
'date',
),
),
);
}

Expand Down
72 changes: 53 additions & 19 deletions WordPress/Sniffs/WP/TimezoneChangeSniff.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace WordPressCS\WordPress\Sniffs\WP;

use WordPressCS\WordPress\AbstractFunctionRestrictionsSniff;
use WordPressCS\WordPress\Sniffs\DateTime\RestrictedFunctionsSniff;

/**
* Disallow the changing of timezone.
Expand All @@ -23,32 +23,66 @@
* class instead of the upstream `Generic.PHP.ForbiddenFunctions` sniff.
* @since 0.13.0 Class name changed: this class is now namespaced.
* @since 1.0.0 This sniff has been moved from the `VIP` category to the `WP` category.
*
* @deprecated 2.2.0 Use the `WordPress.DateTime.RestrictedFunctions` sniff instead.
* This `WordPress.WP.TimezoneChange` sniff will be removed in WPCS 3.0.0.
*/
class TimezoneChangeSniff extends AbstractFunctionRestrictionsSniff {
class TimezoneChangeSniff extends RestrictedFunctionsSniff {

/**
* Groups of functions to restrict.
* Keep track of whether the warnings have been thrown to prevent
* the messages being thrown for every token triggering the sniff.
*
* Example: groups => array(
* 'lambda' => array(
* 'type' => 'error' | 'warning',
* 'message' => 'Use anonymous functions instead please!',
* 'functions' => array( 'file_get_contents', 'create_function' ),
* )
* )
* @since 2.2.0
*
* @var array
*/
private $thrown = array(
'DeprecatedSniff' => false,
'FoundPropertyForDeprecatedSniff' => false,
);

/**
* Don't use.
*
* @deprecated 2.2.0
*
* @return array
*/
public function getGroups() {
return array(
'timezone_change' => array(
'type' => 'error',
'message' => 'Using %s() and similar isn\'t allowed, instead use WP internal timezone support.',
'functions' => array(
'date_default_timezone_set',
),
),
);
$groups = parent::getGroups();
return array( 'timezone_change' => $groups['timezone_change'] );
}

/**
* Don't use.
*
* @since 2.2.0 Added to allow for throwing the deprecation notices.
* @deprecated 2.2.0
*
* @param int $stackPtr The position of the current token in the stack.
*
* @return void|int
*/
public function process_token( $stackPtr ) {
if ( false === $this->thrown['DeprecatedSniff'] ) {
$this->thrown['DeprecatedSniff'] = $this->phpcsFile->addWarning(
'The "WordPress.WP.TimezoneChange" sniff has been deprecated. Use the "WordPress.DateTime.RestrictedFunctions" sniff instead. Please update your custom ruleset.',
0,
'DeprecatedSniff'
);
}

if ( ! empty( $this->exclude )
&& false === $this->thrown['FoundPropertyForDeprecatedSniff']
) {
$this->thrown['FoundPropertyForDeprecatedSniff'] = $this->phpcsFile->addWarning(
'The "WordPress.WP.TimezoneChange" sniff has been deprecated. Use the "WordPress.DateTime.RestrictedFunctions" sniff instead. "exclude" property setting found. Please update your custom ruleset.',
0,
'FoundPropertyForDeprecatedSniff'
);
}

return parent::process_token( $stackPtr );
}
}
9 changes: 9 additions & 0 deletions WordPress/Tests/DateTime/RestrictedFunctionsUnitTest.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

date_default_timezone_set( 'Foo/Bar' ); // Bad.

$date = new DateTime();
$date->setTimezone( new DateTimeZone( 'America/Toronto' ) ); // Yay!

$post_data['post_title'] = sprintf( __( 'Draft created on %1$s at %2$s' ), date( __( 'F j, Y' ), $now ), date( __( 'g:i a' ), $now ) ); // Error.
$post_data['post_title'] = sprintf( __( 'Draft created on %1$s at %2$s' ), gmdate( __( 'F j, Y' ), $now ), gmdate( __( 'g:i a' ), $now ) ); // OK.
44 changes: 44 additions & 0 deletions WordPress/Tests/DateTime/RestrictedFunctionsUnitTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php
/**
* Unit test class for WordPress Coding Standard.
*
* @package WPCS\WordPressCodingStandards
* @link https://github.com/WordPress/WordPress-Coding-Standards
* @license https://opensource.org/licenses/MIT MIT
*/

namespace WordPressCS\WordPress\Tests\DateTime;

use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest;

/**
* Unit test class for the DateTime.RestrictedFunctions sniff.
*
* @package WPCS\WordPressCodingStandards
*
* @since 2.2.0
*/
class RestrictedFunctionsUnitTest extends AbstractSniffUnitTest {

/**
* Returns the lines where errors should occur.
*
* @return array <int line number> => <int number of errors>
*/
public function getErrorList() {
return array(
3 => 1,
8 => 2,
);
}

/**
* Returns the lines where warnings should occur.
*
* @return array <int line number> => <int number of warnings>
*/
public function getWarningList() {
return array();
}

}
3 changes: 0 additions & 3 deletions WordPress/Tests/PHP/RestrictedPHPFunctionsUnitTest.inc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,3 @@
add_action( 'widgets_init', create_function( '', // Error.
'return register_widget( "time_more_on_time_widget" );'
) );

$post_data['post_title'] = sprintf( __( 'Draft created on %1$s at %2$s' ), date( __( 'F j, Y' ), $now ), date( __( 'g:i a' ), $now ) ); // Error.
$post_data['post_title'] = sprintf( __( 'Draft created on %1$s at %2$s' ), gmdate( __( 'F j, Y' ), $now ), gmdate( __( 'g:i a' ), $now ) ); // OK.
1 change: 0 additions & 1 deletion WordPress/Tests/PHP/RestrictedPHPFunctionsUnitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ class RestrictedPHPFunctionsUnitTest extends AbstractSniffUnitTest {
public function getErrorList() {
return array(
3 => 1,
7 => 2,
);
}

Expand Down
6 changes: 4 additions & 2 deletions WordPress/Tests/WP/TimezoneChangeUnitTest.inc
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@

date_default_timezone_set( 'Foo/Bar' ); // Bad.

$date = new DateTime();
$date->setTimezone( new DateTimeZone( 'America/Toronto' ) ); // Yay!
// phpcs:set WordPress.WP.TimezoneChange exclude[] timezone_change
date_default_timezone_set( 'Foo/Bar' ); // OK.

// phpcs:set WordPress.WP.TimezoneChange exclude[]
7 changes: 6 additions & 1 deletion WordPress/Tests/WP/TimezoneChangeUnitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
* @since 0.3.0
* @since 0.13.0 Class name changed: this class is now namespaced.
* @since 1.0.0 This sniff has been moved from the `VIP` category to the `WP` category.
* @since 2.2.0 The sniff has been deprecated. This unit test file now
* only tests that the deprecation warnings are correctly thrown
* and that the sniff falls through to the parent correctly.
*/
class TimezoneChangeUnitTest extends AbstractSniffUnitTest {

Expand All @@ -39,7 +42,9 @@ public function getErrorList() {
* @return array <int line number> => <int number of warnings>
*/
public function getWarningList() {
return array();
return array(
1 => 2,
);
}

}
6 changes: 5 additions & 1 deletion WordPress/ruleset.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
<rule ref="WordPress-Core"/>
-->
<rule ref="WordPress-Docs"/>
<rule ref="WordPress-Extra"/>
<rule ref="WordPress-Extra">
<!-- Prevent duplicate messages + deprecation notice from deprecated sniff. -->
<exclude name="WordPress.WP.TimezoneChange.timezone_change_date_default_timezone_set"/>
<exclude name="WordPress.WP.TimezoneChange.DeprecatedSniff"/>
</rule>

</ruleset>

0 comments on commit 619ced0

Please sign in to comment.