Code Modernization: Remove JSON extension workarounds for PHP < 5.6.

The PHP native JSON extension has been bundled and compiled with PHP by default since version 5.2.0. Because the minimum version of PHP required by WordPress is now 5.6.20 (see #46594 and [45058]), JSON extension related polyfills and backwards compatibility code can now be removed.

This change removes code that supported JSON related functionality on older versions of PHP. This includes (but is not limited to) checks that `json_last_error()` exists, checking and setting the `JSON_UNESCAPED_SLASHES` and `JSON_PRETTY_PRINT` constants if not previously defined, and deprecating the `_wp_json_prepare_data()` function (which was 100% workaround code).

Follow up of [46205].

See #47699.
Props jrf, Clorith, pento.

git-svn-id: https://develop.svn.wordpress.org/trunk@46206 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Jonathan Desrosiers 2019-09-20 20:07:28 +00:00
parent 080e7a609e
commit f6b8632508
7 changed files with 28 additions and 101 deletions

View File

@ -93,13 +93,6 @@ function includes_url() {}
*/
function wp_guess_url() {}
if ( ! function_exists( 'json_encode' ) ) :
/**
* @ignore
*/
function json_encode() {}
endif;
function get_file( $path ) {
if ( function_exists( 'realpath' ) ) {

View File

@ -1116,8 +1116,9 @@ final class WP_Customize_Manager {
return new WP_Error( 'wrong_post_type' );
}
$changeset_data = json_decode( $changeset_post->post_content, true );
if ( function_exists( 'json_last_error' ) && json_last_error() ) {
return new WP_Error( 'json_parse_error', '', json_last_error() );
$last_error = json_last_error();
if ( $last_error ) {
return new WP_Error( 'json_parse_error', '', $last_error );
}
if ( ! is_array( $changeset_data ) ) {
return new WP_Error( 'expected_array' );
@ -2843,13 +2844,9 @@ final class WP_Customize_Manager {
}
// Gather the data for wp_insert_post()/wp_update_post().
$json_options = 0;
if ( defined( 'JSON_UNESCAPED_SLASHES' ) ) {
$json_options |= JSON_UNESCAPED_SLASHES; // Introduced in PHP 5.4. This is only to improve readability as slashes needn't be escaped in storage.
}
$json_options |= JSON_PRETTY_PRINT; // Also introduced in PHP 5.4, but WP defines constant for back compat. See WP Trac #30139.
$post_array = array(
'post_content' => wp_json_encode( $data, $json_options ),
$post_array = array(
// JSON_UNESCAPED_SLASHES is only to improve readability as slashes needn't be escaped in storage.
'post_content' => wp_json_encode( $data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT ),
);
if ( $args['title'] ) {
$post_array['post_title'] = $args['title'];

View File

@ -3721,6 +3721,7 @@ function _wp_die_process_input( $message, $title = '', $args = array() ) {
* Encode a variable into JSON, with some sanity checks.
*
* @since 4.1.0
* @since 5.3.0 No longer handles support for PHP < 5.6.
*
* @param mixed $data Variable (usually an array or object) to encode as JSON.
* @param int $options Optional. Options to be passed to json_encode(). Default 0.
@ -3729,39 +3730,20 @@ function _wp_die_process_input( $message, $title = '', $args = array() ) {
* @return string|false The JSON encoded string, or false if it cannot be encoded.
*/
function wp_json_encode( $data, $options = 0, $depth = 512 ) {
/*
* json_encode() has had extra params added over the years.
* $options was added in 5.3, and $depth in 5.5.
* We need to make sure we call it with the correct arguments.
*/
if ( version_compare( PHP_VERSION, '5.5', '>=' ) ) {
$args = array( $data, $options, $depth );
} elseif ( version_compare( PHP_VERSION, '5.3', '>=' ) ) {
$args = array( $data, $options );
} else {
$args = array( $data );
}
// Prepare the data for JSON serialization.
$args[0] = _wp_json_prepare_data( $data );
// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- json_encode() errors are handled after this call
$json = @call_user_func_array( 'json_encode', $args );
$json = json_encode( $data, $options, $depth );
// If json_encode() was successful, no need to do more sanity checking.
// ... unless we're in an old version of PHP, and json_encode() returned
// a string containing 'null'. Then we need to do more sanity checking.
if ( false !== $json && ( version_compare( PHP_VERSION, '5.5', '>=' ) || false === strpos( $json, 'null' ) ) ) {
if ( false !== $json ) {
return $json;
}
try {
$args[0] = _wp_json_sanity_check( $data, $depth );
$data = _wp_json_sanity_check( $data, $depth );
} catch ( Exception $e ) {
return false;
}
return call_user_func_array( 'json_encode', $args );
return json_encode( $data, $options, $depth );
}
/**
@ -3865,48 +3847,17 @@ function _wp_json_convert_string( $string ) {
* This supports the JsonSerializable interface for PHP 5.2-5.3 as well.
*
* @ignore
* @since 4.4.0
* @access private
* @since 4.4.0
* @deprecated 5.3.0 This function is no longer needed as support for PHP 5.2-5.3
* has been dropped.
* @access private
*
* @param mixed $data Native representation.
* @return bool|int|float|null|string|array Data ready for `json_encode()`.
*/
function _wp_json_prepare_data( $data ) {
if ( ! defined( 'WP_JSON_SERIALIZE_COMPATIBLE' ) || WP_JSON_SERIALIZE_COMPATIBLE === false ) {
return $data;
}
switch ( gettype( $data ) ) {
case 'boolean':
case 'integer':
case 'double':
case 'string':
case 'NULL':
// These values can be passed through.
return $data;
case 'array':
// Arrays must be mapped in case they also return objects.
return array_map( '_wp_json_prepare_data', $data );
case 'object':
// If this is an incomplete object (__PHP_Incomplete_Class), bail.
if ( ! is_object( $data ) ) {
return null;
}
if ( $data instanceof JsonSerializable ) {
$data = $data->jsonSerialize();
} else {
$data = get_object_vars( $data );
}
// Now, pass the array (or whatever was returned from jsonSerialize through).
return _wp_json_prepare_data( $data );
default:
return null;
}
_deprecated_function( __FUNCTION__, '5.3.0' );
return $data;
}
/**

View File

@ -639,21 +639,16 @@ class WP_REST_Request implements ArrayAccess {
/*
* Check for a parsing error.
*
* Note that due to WP's JSON compatibility functions, json_last_error
* might not be defined: https://core.trac.wordpress.org/ticket/27799
*/
if ( null === $params && ( ! function_exists( 'json_last_error' ) || JSON_ERROR_NONE !== json_last_error() ) ) {
if ( null === $params && JSON_ERROR_NONE !== json_last_error() ) {
// Ensure subsequent calls receive error instance.
$this->parsed_json = false;
$error_data = array(
'status' => WP_Http::BAD_REQUEST,
'status' => WP_Http::BAD_REQUEST,
'json_error_code' => json_last_error(),
'json_error_message' => json_last_error_msg(),
);
if ( function_exists( 'json_last_error' ) ) {
$error_data['json_error_code'] = json_last_error();
$error_data['json_error_message'] = json_last_error_msg();
}
return new WP_Error( 'rest_invalid_json', __( 'Invalid JSON body passed.' ), $error_data );
}

View File

@ -1001,14 +1001,9 @@ class WP_REST_Server {
* @return bool|string Boolean false or string error message.
*/
protected function get_json_last_error() {
// See https://core.trac.wordpress.org/ticket/27799.
if ( ! function_exists( 'json_last_error' ) ) {
return false;
}
$last_error_code = json_last_error();
if ( ( defined( 'JSON_ERROR_NONE' ) && JSON_ERROR_NONE === $last_error_code ) || empty( $last_error_code ) ) {
if ( JSON_ERROR_NONE === $last_error_code || empty( $last_error_code ) ) {
return false;
}

View File

@ -1856,9 +1856,7 @@ class Tests_WP_Customize_Manager extends WP_UnitTestCase {
$r = $manager->save_changeset_post( $args );
$this->assertInstanceOf( 'WP_Error', $r );
if ( function_exists( 'json_last_error' ) ) {
$this->assertEquals( 'json_parse_error', $r->get_error_code() );
}
$this->assertEquals( 'json_parse_error', $r->get_error_code() );
wp_update_post(
array(

View File

@ -488,16 +488,14 @@ class WP_Test_REST_Schema_Initialization extends WP_Test_REST_TestCase {
);
$this->assertTrue( ! empty( $data ), $route['name'] . ' route should return data.' );
if ( version_compare( PHP_VERSION, '5.4', '>=' ) ) {
$fixture = $this->normalize_fixture( $data, $route['name'] );
$mocked_responses .= "\nmockedApiResponse." . $route['name'] . ' = '
. json_encode( $fixture, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES )
. ";\n";
}
$fixture = $this->normalize_fixture( $data, $route['name'] );
$mocked_responses .= "\nmockedApiResponse." . $route['name'] . ' = '
. json_encode( $fixture, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES )
. ";\n";
}
// Only generate API client fixtures in single site and when required JSON_* constants are supported.
if ( ! is_multisite() && version_compare( PHP_VERSION, '5.4', '>=' ) ) {
if ( ! is_multisite() ) {
// Save the route object for QUnit tests.
$file = dirname( DIR_TESTROOT ) . '/qunit/fixtures/wp-api-generated.js';
file_put_contents( $file, $mocked_responses );