Quellcode durchsuchen

Extracting JsonFile additions for prettifying JSON

Justin Rainbow vor 13 Jahren
Ursprung
Commit
447230d77a
2 geänderte Dateien mit 92 neuen und 6 gelöschten Zeilen
  1. 75 6
      src/Composer/Json/JsonFile.php
  2. 17 0
      tests/Composer/Test/Json/JsonFileTest.php

+ 75 - 6
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;
     }
 
     /**

+ 17 - 0
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));
+    }
+
 }