jenkins-bot has submitted this change and it was merged. Change subject: FormatJson: Make it possible to change the indent string ......................................................................
FormatJson: Make it possible to change the indent string This is to allow consistency with MediaWiki PHP and JS files (e.g. when generating JSON i18n files), not because tabs are "better" than spaces for indenting code (both have advantages and disadvantages). Because PHP's json_encode() function hardcodes the indent string, using tabs has a performance cost (in post-processing the output) and is less suitable for web output; thus the API and ResourceLoader debug mode will continue to use four spaces. Adjusting the maintenance scripts and JSON files is left to separate change sets. Bug: 63444 Change-Id: Ic915c50b0acd2e236940b70d5dd48ea87954c9d5 --- M RELEASE-NOTES-1.24 M includes/json/FormatJson.php M tests/phpunit/includes/json/FormatJsonTest.php 3 files changed, 61 insertions(+), 24 deletions(-) Approvals: Anomie: Looks good to me, approved jenkins-bot: Verified diff --git a/RELEASE-NOTES-1.24 b/RELEASE-NOTES-1.24 index 0e7fbe6..4e2b6a9 100644 --- a/RELEASE-NOTES-1.24 +++ b/RELEASE-NOTES-1.24 @@ -11,6 +11,8 @@ === Configuration changes in 1.24 === === New features in 1.24 === +* (bug 63444) Made it possible to change the indent string (default: 4 spaces) + used by FormatJson::encode(). === Bug fixes in 1.24 === * (bug 62258) A bug was fixed in File::getUnscaledThumb when a height diff --git a/includes/json/FormatJson.php b/includes/json/FormatJson.php index 83718c3..97d98a4 100644 --- a/includes/json/FormatJson.php +++ b/includes/json/FormatJson.php @@ -95,11 +95,17 @@ * (cf. FormatJson::XMLMETA_OK). Use Xml::encodeJsVar() instead in such cases. * * @param mixed $value The value to encode. Can be any type except a resource. - * @param bool $pretty If true, add non-significant whitespace to improve readability. + * @param string|bool $pretty If a string, add non-significant whitespace to improve + * readability, using that string for indentation. If true, use the default indent + * string (four spaces). * @param int $escaping Bitfield consisting of _OK class constants * @return string|bool: String if successful; false upon failure */ public static function encode( $value, $pretty = false, $escaping = 0 ) { + if ( !is_string( $pretty ) ) { + $pretty = $pretty ? ' ' : false; + } + if ( defined( 'JSON_UNESCAPED_UNICODE' ) ) { return self::encode54( $value, $pretty, $escaping ); } @@ -125,7 +131,7 @@ * JSON encoder wrapper for PHP >= 5.4, which supports useful encoding options. * * @param mixed $value - * @param bool $pretty + * @param string|bool $pretty * @param int $escaping * @return string|bool */ @@ -134,7 +140,7 @@ // which is hardly useful when '<' and '>' are escaped (and inadequate), and such // escaping negatively impacts the human readability of URLs and similar strings. $options = JSON_UNESCAPED_SLASHES; - $options |= $pretty ? JSON_PRETTY_PRINT : 0; + $options |= $pretty !== false ? JSON_PRETTY_PRINT : 0; $options |= ( $escaping & self::UTF8_OK ) ? JSON_UNESCAPED_UNICODE : 0; $options |= ( $escaping & self::XMLMETA_OK ) ? 0 : ( JSON_HEX_TAG | JSON_HEX_AMP ); $json = json_encode( $value, $options ); @@ -142,10 +148,22 @@ return false; } - if ( $pretty ) { + if ( $pretty !== false ) { // Remove whitespace inside empty arrays/objects; different JSON encoders // vary on this, and we want our output to be consistent across implementations. $json = preg_replace( self::WS_CLEANUP_REGEX, '', $json ); + if ( $pretty !== ' ' ) { + // Change the four-space indent to a tab indent + $json = str_replace( "\n ", "\n\t", $json ); + while ( strpos( $json, "\t " ) !== false ) { + $json = str_replace( "\t ", "\t\t", $json ); + } + + if ( $pretty !== "\t" ) { + // Change the tab indent to the provided indent + $json = str_replace( "\t", $pretty, $json ); + } + } } if ( $escaping & self::UTF8_OK ) { $json = str_replace( self::$badChars, self::$badCharsEscaped, $json ); @@ -159,7 +177,7 @@ * Therefore, the missing options are implemented here purely in PHP code. * * @param mixed $value - * @param bool $pretty + * @param string|bool $pretty * @param int $escaping * @return string|bool */ @@ -188,8 +206,8 @@ $json = str_replace( self::$badChars, self::$badCharsEscaped, $json ); } - if ( $pretty ) { - return self::prettyPrint( $json ); + if ( $pretty !== false ) { + return self::prettyPrint( $json, $pretty ); } return $json; @@ -200,9 +218,10 @@ * Only needed for PHP < 5.4, which lacks the JSON_PRETTY_PRINT option. * * @param string $json + * @param string $indentString * @return string */ - private static function prettyPrint( $json ) { + private static function prettyPrint( $json, $indentString ) { $buf = ''; $indent = 0; $json = strtr( $json, array( '\\\\' => '\\\\', '\"' => "\x01" ) ); @@ -217,11 +236,11 @@ ++$indent; // falls through case ',': - $buf .= $json[$i] . "\n" . str_repeat( ' ', $indent ); + $buf .= $json[$i] . "\n" . str_repeat( $indentString, $indent ); break; case ']': case '}': - $buf .= "\n" . str_repeat( ' ', --$indent ) . $json[$i]; + $buf .= "\n" . str_repeat( $indentString, --$indent ) . $json[$i]; break; case '"': $skip = strcspn( $json, '"', $i + 1 ) + 2; diff --git a/tests/phpunit/includes/json/FormatJsonTest.php b/tests/phpunit/includes/json/FormatJsonTest.php index 8359f0d..307b355 100644 --- a/tests/phpunit/includes/json/FormatJsonTest.php +++ b/tests/phpunit/includes/json/FormatJsonTest.php @@ -5,7 +5,22 @@ */ class FormatJsonTest extends MediaWikiTestCase { - public function testEncoderPrettyPrinting() { + public static function provideEncoderPrettyPrinting() { + return array( + // Four spaces + array( true, ' ' ), + array( ' ', ' ' ), + // Two spaces + array( ' ', ' ' ), + // One tab + array( "\t", "\t" ), + ); + } + + /** + * @dataProvider provideEncoderPrettyPrinting + */ + public function testEncoderPrettyPrinting( $pretty, $expectedIndent ) { $obj = array( 'emptyObject' => new stdClass, 'emptyArray' => array(), @@ -22,23 +37,24 @@ ), ); - // 4 space indent, no trailing whitespace, no trailing linefeed + // No trailing whitespace, no trailing linefeed $json = '{ - "emptyObject": {}, - "emptyArray": [], - "string": "foobar\\\\", - "filledArray": [ - [ - 123, - 456 - ], - "\"7\":[\"8\",{\"9\":\"10\"}]", - "{\n\t\"emptyObject\": {\n\t},\n\t\"emptyArray\": [ ]\n}" - ] + "emptyObject": {}, + "emptyArray": [], + "string": "foobar\\\\", + "filledArray": [ + [ + 123, + 456 + ], + "\"7\":[\"8\",{\"9\":\"10\"}]", + "{\n\t\"emptyObject\": {\n\t},\n\t\"emptyArray\": [ ]\n}" + ] }'; $json = str_replace( "\r", '', $json ); // Windows compat - $this->assertSame( $json, FormatJson::encode( $obj, true ) ); + $json = str_replace( "\t", $expectedIndent, $json ); + $this->assertSame( $json, FormatJson::encode( $obj, $pretty ) ); } public static function provideEncodeDefault() { -- To view, visit https://gerrit.wikimedia.org/r/123518 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Ic915c50b0acd2e236940b70d5dd48ea87954c9d5 Gerrit-PatchSet: 4 Gerrit-Project: mediawiki/core Gerrit-Branch: master Gerrit-Owner: PleaseStand <pleasest...@live.com> Gerrit-Reviewer: Anomie <bjor...@wikimedia.org> Gerrit-Reviewer: Brian Wolff <bawolff...@gmail.com> Gerrit-Reviewer: Kaldari <rkald...@wikimedia.org> Gerrit-Reviewer: Nikerabbit <niklas.laxst...@gmail.com> Gerrit-Reviewer: Siebrand <siebr...@kitano.nl> Gerrit-Reviewer: Tim Landscheidt <t...@tim-landscheidt.de> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits