diff --git a/.travis.yml b/.travis.yml index a1ffd8aa23..cfd15e10b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,6 +29,8 @@ matrix: name: PHP Linting - env: WP_TRAVISCI=travis:js WP_INSTALL=false name: JS Tests + - env: WP_TRAVISCI=test:compat COMPOSER_INSTALL=true NPM_INSTALL=false WP_INSTALL=false + name: "PHP Compatibility Check" - env: LOCAL_PHP=7.3-fpm WP_TRAVISCI=test:php name: "PHPUnit Tests: PHP 7.3" - env: LOCAL_PHP=7.3-fpm LOCAL_PHP_MEMCACHED=true WP_TRAVISCI=test:php @@ -46,6 +48,7 @@ matrix: - env: LOCAL_PHP=8.0-fpm WP_TRAVISCI=test:php name: "PHPUnit Tests: PHP 8.0" allow_failures: + - env: WP_TRAVISCI=test:compat COMPOSER_INSTALL=true NPM_INSTALL=false WP_INSTALL=false - env: LOCAL_PHP=7.4-fpm WP_TRAVISCI=test:php - env: LOCAL_PHP=8.0-fpm WP_TRAVISCI=test:php fast_finish: true @@ -120,6 +123,8 @@ script: docker-compose run --rm php composer format && docker-compose run --rm php composer lint:errors && docker-compose run --rm php composer lint tests + elif [[ "$WP_TRAVISCI" == "test:compat" ]]; then + docker-compose run --rm php composer compat else npm run grunt $WP_TRAVISCI fi diff --git a/composer.json b/composer.json index ccc0e2a796..1e0a2b383f 100644 --- a/composer.json +++ b/composer.json @@ -14,9 +14,11 @@ }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "~0.5.0", - "wp-coding-standards/wpcs": "~2.1.0" + "wp-coding-standards/wpcs": "~2.1.0", + "phpcompatibility/phpcompatibility-wp": "^2.1.0" }, "scripts": { + "compat": "@php ./vendor/squizlabs/php_codesniffer/bin/phpcs --standard=phpcompat.xml.dist --report=summary,source", "format": "@php ./vendor/squizlabs/php_codesniffer/bin/phpcbf --report=summary,source --cache -d memory_limit=256M", "lint": "@php ./vendor/squizlabs/php_codesniffer/bin/phpcs --report=summary,source --cache -d memory_limit=256M", "lint:errors": "@lint -n" diff --git a/composer.lock b/composer.lock index 18664c1933..c725fb4e8c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "56c797c5309702adf0f49bd274a364f3", + "content-hash": "ca8f46e0b3cba61c076c033cc7143d3a", "packages": [], "packages-dev": [ { @@ -73,6 +73,166 @@ ], "time": "2018-10-26T13:21:45+00:00" }, + { + "name": "phpcompatibility/php-compatibility", + "version": "9.3.1", + "source": { + "type": "git", + "url": "https://github.com/PHPCompatibility/PHPCompatibility.git", + "reference": "9999344e47e7af6b00e1a898eacc4e4368fb7196" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/9999344e47e7af6b00e1a898eacc4e4368fb7196", + "reference": "9999344e47e7af6b00e1a898eacc4e4368fb7196", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "squizlabs/php_codesniffer": "^2.3 || ^3.0.2" + }, + "conflict": { + "squizlabs/php_codesniffer": "2.6.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.5 || ^5.0 || ^6.0 || ^7.0" + }, + "suggest": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.", + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + }, + "type": "phpcodesniffer-standard", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Wim Godden", + "homepage": "https://github.com/wimg", + "role": "lead" + }, + { + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", + "role": "lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors" + } + ], + "description": "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.", + "homepage": "http://techblog.wimgodden.be/tag/codesniffer/", + "keywords": [ + "compatibility", + "phpcs", + "standards" + ], + "time": "2019-09-05T18:36:49+00:00" + }, + { + "name": "phpcompatibility/phpcompatibility-paragonie", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie.git", + "reference": "b1bb79a7cab1fb856b56f1b5cf110b6e52d8e936" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/b1bb79a7cab1fb856b56f1b5cf110b6e52d8e936", + "reference": "b1bb79a7cab1fb856b56f1b5cf110b6e52d8e936", + "shasum": "" + }, + "require": { + "phpcompatibility/php-compatibility": "^9.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.5", + "paragonie/random_compat": "dev-master", + "paragonie/sodium_compat": "dev-master" + }, + "suggest": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.", + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + }, + "type": "phpcodesniffer-standard", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Wim Godden", + "role": "lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "lead" + } + ], + "description": "A set of rulesets for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by the Paragonie polyfill libraries.", + "homepage": "http://phpcompatibility.com/", + "keywords": [ + "compatibility", + "paragonie", + "phpcs", + "polyfill", + "standards" + ], + "time": "2019-08-28T15:58:19+00:00" + }, + { + "name": "phpcompatibility/phpcompatibility-wp", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/PHPCompatibility/PHPCompatibilityWP.git", + "reference": "41bef18ba688af638b7310666db28e1ea9158b2f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/41bef18ba688af638b7310666db28e1ea9158b2f", + "reference": "41bef18ba688af638b7310666db28e1ea9158b2f", + "shasum": "" + }, + "require": { + "phpcompatibility/php-compatibility": "^9.0", + "phpcompatibility/phpcompatibility-paragonie": "^1.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.5" + }, + "suggest": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.", + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + }, + "type": "phpcodesniffer-standard", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Wim Godden", + "role": "lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "lead" + } + ], + "description": "A ruleset for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by WordPress.", + "homepage": "http://phpcompatibility.com/", + "keywords": [ + "compatibility", + "phpcs", + "standards", + "wordpress" + ], + "time": "2019-08-28T14:22:28+00:00" + }, { "name": "squizlabs/php_codesniffer", "version": "3.4.0", @@ -176,7 +336,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=5.6" + "php": ">=5.6" }, "platform-dev": [] } diff --git a/phpcompat.xml.dist b/phpcompat.xml.dist new file mode 100644 index 0000000000..110b19cc63 --- /dev/null +++ b/phpcompat.xml.dist @@ -0,0 +1,64 @@ + + + Apply PHP compatibility checks to all WordPress Core files + + + + + + + + + + + + + + + + + + + + + + + + + + ./src/ + + + /node_modules/* + + + /vendor/* + + + + /random_compat/byte_safe_strings\.php$ + + + /random_compat/random_bytes_mcrypt\.php$ + + + /random_compat/random_bytes_mcrypt\.php$ + + + /random_compat/random_bytes_mcrypt\.php$ + + + + + /src/wp-includes/wp-db\.php + + diff --git a/src/wp-admin/includes/class-wp-debug-data.php b/src/wp-admin/includes/class-wp-debug-data.php index 4708e6187c..5ffec9825f 100644 --- a/src/wp-admin/includes/class-wp-debug-data.php +++ b/src/wp-admin/includes/class-wp-debug-data.php @@ -728,7 +728,7 @@ class WP_Debug_Data { if ( isset( $wpdb->use_mysqli ) && $wpdb->use_mysqli ) { $client_version = $wpdb->dbh->client_info; } else { - // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysql_get_client_info + // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysql_get_client_info,PHPCompatibility.Extensions.RemovedExtensions.mysql_DeprecatedRemoved if ( preg_match( '|[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}|', mysql_get_client_info(), $matches ) ) { $client_version = $matches[0]; } else { diff --git a/src/wp-admin/includes/class-wp-site-health.php b/src/wp-admin/includes/class-wp-site-health.php index 5f7c6bc7b7..27b29ad76f 100644 --- a/src/wp-admin/includes/class-wp-site-health.php +++ b/src/wp-admin/includes/class-wp-site-health.php @@ -158,7 +158,7 @@ class WP_Site_Health { // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysqli_get_server_info $mysql_server_type = mysqli_get_server_info( $wpdb->dbh ); } else { - // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysql_get_server_info + // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysql_get_server_info,PHPCompatibility.Extensions.RemovedExtensions.mysql_DeprecatedRemoved $mysql_server_type = mysql_get_server_info( $wpdb->dbh ); } @@ -1171,7 +1171,7 @@ class WP_Site_Health { // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysqli_get_client_info $mysql_client_version = mysqli_get_client_info(); } else { - // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysql_get_client_info + // phpcs:ignore WordPress.DB.RestrictedFunctions.mysql_mysql_get_client_info,PHPCompatibility.Extensions.RemovedExtensions.mysql_DeprecatedRemoved $mysql_client_version = mysql_get_client_info(); } diff --git a/src/wp-admin/includes/file.php b/src/wp-admin/includes/file.php index 11977a8662..9cd626ec0b 100644 --- a/src/wp-admin/includes/file.php +++ b/src/wp-admin/includes/file.php @@ -1280,6 +1280,7 @@ function verify_file_signature( $filename, $signatures, $filename_for_errors = f ), array( 'php' => phpversion(), + // phpcs:ignore PHPCompatibility.Constants.NewConstants.sodium_library_versionFound 'sodium' => defined( 'SODIUM_LIBRARY_VERSION' ) ? SODIUM_LIBRARY_VERSION : ( defined( 'ParagonIE_Sodium_Compat::VERSION_STRING' ) ? ParagonIE_Sodium_Compat::VERSION_STRING : false ), ) ); @@ -1313,6 +1314,7 @@ function verify_file_signature( $filename, $signatures, $filename_for_errors = f ), array( 'php' => phpversion(), + // phpcs:ignore PHPCompatibility.Constants.NewConstants.sodium_library_versionFound 'sodium' => defined( 'SODIUM_LIBRARY_VERSION' ) ? SODIUM_LIBRARY_VERSION : ( defined( 'ParagonIE_Sodium_Compat::VERSION_STRING' ) ? ParagonIE_Sodium_Compat::VERSION_STRING : false ), 'polyfill_is_fast' => false, 'max_execution_time' => ini_get( 'max_execution_time' ), @@ -1386,6 +1388,7 @@ function verify_file_signature( $filename, $signatures, $filename_for_errors = f 'skipped_key' => $skipped_key, 'skipped_sig' => $skipped_signature, 'php' => phpversion(), + // phpcs:ignore PHPCompatibility.Constants.NewConstants.sodium_library_versionFound 'sodium' => defined( 'SODIUM_LIBRARY_VERSION' ) ? SODIUM_LIBRARY_VERSION : ( defined( 'ParagonIE_Sodium_Compat::VERSION_STRING' ) ? ParagonIE_Sodium_Compat::VERSION_STRING : false ), ) ); diff --git a/src/wp-admin/includes/upgrade.php b/src/wp-admin/includes/upgrade.php index 79a23a6308..3b2d62da7c 100644 --- a/src/wp-admin/includes/upgrade.php +++ b/src/wp-admin/includes/upgrade.php @@ -2475,7 +2475,7 @@ function get_alloptions_110() { * @param string $setting Option name. * @return mixed */ -function __get_option( $setting ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionDoubleUnderscore +function __get_option( $setting ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionDoubleUnderscore,PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.FunctionDoubleUnderscore global $wpdb; if ( $setting == 'home' && defined( 'WP_HOME' ) ) { diff --git a/src/wp-includes/author-template.php b/src/wp-includes/author-template.php index 878fb9e409..a14b628909 100644 --- a/src/wp-includes/author-template.php +++ b/src/wp-includes/author-template.php @@ -565,6 +565,6 @@ function is_multi_author() { * @since 3.2.0 * @access private */ -function __clear_multi_author_cache() { //phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionDoubleUnderscore +function __clear_multi_author_cache() { //phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionDoubleUnderscore,PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.FunctionDoubleUnderscore delete_transient( 'is_multi_author' ); } diff --git a/src/wp-includes/deprecated.php b/src/wp-includes/deprecated.php index 215213f70b..98da670cc1 100644 --- a/src/wp-includes/deprecated.php +++ b/src/wp-includes/deprecated.php @@ -1798,7 +1798,7 @@ function _nc( $single, $plural, $number, $domain = 'default' ) { * @deprecated 2.8.0 Use _n() * @see _n() */ -function __ngettext( ...$args ) { +function __ngettext( ...$args ) { // phpcs:ignore PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.FunctionDoubleUnderscore _deprecated_function( __FUNCTION__, '2.8.0', '_n()' ); return _n( ...$args ); } @@ -1810,7 +1810,7 @@ function __ngettext( ...$args ) { * @deprecated 2.8.0 Use _n_noop() * @see _n_noop() */ -function __ngettext_noop( ...$args ) { +function __ngettext_noop( ...$args ) { // phpcs:ignore PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.FunctionDoubleUnderscore _deprecated_function( __FUNCTION__, '2.8.0', '_n_noop()' ); return _n_noop( ...$args ); diff --git a/src/wp-includes/functions.php b/src/wp-includes/functions.php index d3dded8078..c49b0e0e7e 100644 --- a/src/wp-includes/functions.php +++ b/src/wp-includes/functions.php @@ -5743,7 +5743,7 @@ function get_file_data( $file, $default_headers, $context = '' ) { * * @return true True. */ -function __return_true() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionDoubleUnderscore +function __return_true() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionDoubleUnderscore,PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.FunctionDoubleUnderscore return true; } @@ -5758,7 +5758,7 @@ function __return_true() { // phpcs:ignore WordPress.NamingConventions.ValidFunc * * @return false False. */ -function __return_false() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionDoubleUnderscore +function __return_false() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionDoubleUnderscore,PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.FunctionDoubleUnderscore return false; } @@ -5771,7 +5771,7 @@ function __return_false() { // phpcs:ignore WordPress.NamingConventions.ValidFun * * @return int 0. */ -function __return_zero() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionDoubleUnderscore +function __return_zero() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionDoubleUnderscore,PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.FunctionDoubleUnderscore return 0; } @@ -5784,7 +5784,7 @@ function __return_zero() { // phpcs:ignore WordPress.NamingConventions.ValidFunc * * @return array Empty array. */ -function __return_empty_array() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionDoubleUnderscore +function __return_empty_array() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionDoubleUnderscore,PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.FunctionDoubleUnderscore return array(); } @@ -5797,7 +5797,7 @@ function __return_empty_array() { // phpcs:ignore WordPress.NamingConventions.Va * * @return null Null value. */ -function __return_null() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionDoubleUnderscore +function __return_null() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionDoubleUnderscore,PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.FunctionDoubleUnderscore return null; } @@ -5812,7 +5812,7 @@ function __return_null() { // phpcs:ignore WordPress.NamingConventions.ValidFunc * * @return string Empty string. */ -function __return_empty_string() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionDoubleUnderscore +function __return_empty_string() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionDoubleUnderscore,PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.FunctionDoubleUnderscore return ''; } diff --git a/src/wp-includes/general-template.php b/src/wp-includes/general-template.php index 28d0e399e9..32d5595bb1 100644 --- a/src/wp-includes/general-template.php +++ b/src/wp-includes/general-template.php @@ -4684,7 +4684,7 @@ function readonly( $readonly, $current = true, $echo = true ) { * @param string $type The type of checked|selected|disabled|readonly we are doing * @return string html attribute or empty string */ -function __checked_selected_helper( $helper, $current, $echo, $type ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionDoubleUnderscore +function __checked_selected_helper( $helper, $current, $echo, $type ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionDoubleUnderscore,PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.FunctionDoubleUnderscore if ( (string) $helper === (string) $current ) { $result = " $type='$type'"; } else {