From 447230d77aa1389285fdea337a9689ad95aa3920 Mon Sep 17 00:00:00 2001 From: Justin Rainbow Date: Mon, 16 Jan 2012 16:42:30 -0700 Subject: [PATCH] Extracting JsonFile additions for prettifying JSON --- src/Composer/Json/JsonFile.php | 81 +++++++++++++++++++++-- tests/Composer/Test/Json/JsonFileTest.php | 17 +++++ 2 files changed, 92 insertions(+), 6 deletions(-) diff --git a/src/Composer/Json/JsonFile.php b/src/Composer/Json/JsonFile.php index 22aa4d265..6b05dff12 100644 --- a/src/Composer/Json/JsonFile.php +++ b/src/Composer/Json/JsonFile.php @@ -15,11 +15,6 @@ namespace Composer\Json; use Composer\Repository\RepositoryManager; use Composer\Composer; -// defined as of PHP 5.4 -if (!defined('JSON_PRETTY_PRINT')) { - define('JSON_PRETTY_PRINT', 128); -} - /** * Reads/writes json files. * @@ -96,7 +91,81 @@ class JsonFile ); } } - file_put_contents($this->path, json_encode($hash, JSON_PRETTY_PRINT)); + file_put_contents($this->path, $this->encode($hash)); + } + + /** + * Indents a flat JSON string to make it more human-readable + * + * Original code for this function can be found at: + * http://recursive-design.com/blog/2008/03/11/format-json-with-php/ + * + * @param array $hash Data to encode into a formatted JSON string + * @return string Indented version of the original JSON string + */ + public function encode(array $hash) + { + if (defined('JSON_PRETTY_PRINT')) { + return json_encode($hash, JSON_PRETTY_PRINT); + } + + $json = json_encode($hash); + + $result = ''; + $pos = 0; + $strLen = strlen($json); + $indentStr = ' '; + $newLine = "\n"; + $prevChar = ''; + $outOfQuotes = true; + + for ($i = 0; $i <= $strLen; $i++) { + // Grab the next character in the string + $char = substr($json, $i, 1); + + // Are we inside a quoted string? + if ('"' === $char && '\\' !== $prevChar) { + $outOfQuotes = !$outOfQuotes; + } else if (':' === $char && $outOfQuotes) { + // Add a space after the : character + $char .= ' '; + } else if (('}' === $char || ']' === $char) && $outOfQuotes) { + $pos--; + + if ('{' !== $prevChar && '[' !== $prevChar) { + // If this character is the end of an element, + // output a new line and indent the next line + $result .= $newLine; + for ($j = 0; $j < $pos; $j++) { + $result .= $indentStr; + } + } else { + // Collapse empty {} and [] + $result = rtrim($result); + } + } + + // Add the character to the result string + $result .= $char; + + // If the last character was the beginning of an element, + // output a new line and indent the next line + if ((',' === $char || '{' === $char || '[' === $char) && $outOfQuotes) { + $result .= $newLine; + + if ('{' === $char || '[' === $char) { + $pos++; + } + + for ($j = 0; $j < $pos; $j++) { + $result .= $indentStr; + } + } + + $prevChar = $char; + } + + return $result; } /** diff --git a/tests/Composer/Test/Json/JsonFileTest.php b/tests/Composer/Test/Json/JsonFileTest.php index 93f7ecef7..75e798388 100644 --- a/tests/Composer/Test/Json/JsonFileTest.php +++ b/tests/Composer/Test/Json/JsonFileTest.php @@ -84,6 +84,15 @@ class JsonFileTest extends \PHPUnit_Framework_TestCase $this->expectParseException('missing comma on line 2, char 21', $json); } + public function testSimpleJsonString() + { + $data = array('name' => 'composer/composer'); + $json = '{ + "name": "composer\/composer" +}'; + $this->assertJsonFormat($json, $data); + } + private function expectParseException($text, $json) { try { @@ -93,4 +102,12 @@ class JsonFileTest extends \PHPUnit_Framework_TestCase $this->assertContains($text, $e->getMessage()); } } + + private function assertJsonFormat($json, $data) + { + $file = new JsonFile('composer.json'); + + $this->assertEquals($json, $file->encode($data)); + } + }