parent
16d1b11c26
commit
1c9fbeb978
|
@ -42,12 +42,16 @@ class JsonFile
|
|||
|
||||
public const COMPOSER_SCHEMA_PATH = __DIR__ . '/../../../res/composer-schema.json';
|
||||
|
||||
public const INDENT_DEFAULT = ' ';
|
||||
|
||||
/** @var string */
|
||||
private $path;
|
||||
/** @var ?HttpDownloader */
|
||||
private $httpDownloader;
|
||||
/** @var ?IOInterface */
|
||||
private $io;
|
||||
/** @var string */
|
||||
private $indent = self::INDENT_DEFAULT;
|
||||
|
||||
/**
|
||||
* Initializes json file reader/parser.
|
||||
|
@ -117,6 +121,8 @@ class JsonFile
|
|||
throw new \RuntimeException('Could not read '.$this->path);
|
||||
}
|
||||
|
||||
$this->indent = self::detectIndenting($json);
|
||||
|
||||
return static::parseJson($json, $this->path);
|
||||
}
|
||||
|
||||
|
@ -131,7 +137,7 @@ class JsonFile
|
|||
public function write(array $hash, int $options = JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)
|
||||
{
|
||||
if ($this->path === 'php://memory') {
|
||||
file_put_contents($this->path, static::encode($hash, $options));
|
||||
file_put_contents($this->path, static::encode($hash, $options, $this->indent));
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -153,7 +159,7 @@ class JsonFile
|
|||
$retries = 3;
|
||||
while ($retries--) {
|
||||
try {
|
||||
$this->filePutContentsIfModified($this->path, static::encode($hash, $options). ($options & JSON_PRETTY_PRINT ? "\n" : ''));
|
||||
$this->filePutContentsIfModified($this->path, static::encode($hash, $options, $this->indent). ($options & JSON_PRETTY_PRINT ? "\n" : ''));
|
||||
break;
|
||||
} catch (\Exception $e) {
|
||||
if ($retries > 0) {
|
||||
|
@ -262,15 +268,28 @@ class JsonFile
|
|||
*
|
||||
* @param mixed $data Data to encode into a formatted JSON string
|
||||
* @param int $options json_encode options (defaults to JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)
|
||||
* @param string $indent Indentation string
|
||||
* @return string Encoded json
|
||||
*/
|
||||
public static function encode($data, int $options = 448)
|
||||
public static function encode($data, int $options = 448, string $indent = self::INDENT_DEFAULT): string
|
||||
{
|
||||
$json = json_encode($data, $options);
|
||||
|
||||
if (false === $json) {
|
||||
self::throwEncodeError(json_last_error());
|
||||
}
|
||||
|
||||
if (($options & JSON_PRETTY_PRINT) > 0 && $indent !== self::INDENT_DEFAULT ) {
|
||||
// Pretty printing and not using default indentation
|
||||
return Preg::replaceCallback(
|
||||
'#^ {4,}#m',
|
||||
static function ($match) use ($indent): string {
|
||||
return str_repeat($indent, (int)(strlen($match[0] ?? '') / 4));
|
||||
},
|
||||
$json
|
||||
);
|
||||
}
|
||||
|
||||
return $json;
|
||||
}
|
||||
|
||||
|
@ -279,6 +298,7 @@ class JsonFile
|
|||
*
|
||||
* @param int $code return code of json_last_error function
|
||||
* @throws \RuntimeException
|
||||
* @return never
|
||||
*/
|
||||
private static function throwEncodeError(int $code): void
|
||||
{
|
||||
|
@ -356,4 +376,12 @@ class JsonFile
|
|||
$result->getDetails());
|
||||
}
|
||||
}
|
||||
|
||||
public static function detectIndenting(?string $json): string
|
||||
{
|
||||
if (Preg::isMatchStrictGroups('#^([ \t]+)"#m', $json ?? '', $match)) {
|
||||
return $match[1];
|
||||
}
|
||||
return self::INDENT_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -561,10 +561,6 @@ class JsonManipulator
|
|||
|
||||
protected function detectIndenting(): void
|
||||
{
|
||||
if (Preg::isMatchStrictGroups('{^([ \t]+)"}m', $this->contents, $match)) {
|
||||
$this->indent = $match[1];
|
||||
} else {
|
||||
$this->indent = ' ';
|
||||
}
|
||||
$this->indent = JsonFile::detectIndenting($this->contents);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"foo": "bar"
|
||||
}
|
|
@ -364,6 +364,29 @@ class JsonFileTest extends TestCase
|
|||
$this->assertEquals($data, $doubleData);
|
||||
}
|
||||
|
||||
public function testPreserveIndentationAfterRead(): void
|
||||
{
|
||||
copy(__DIR__.'/Fixtures/tabs.json', __DIR__.'/Fixtures/tabs2.json');
|
||||
$jsonFile = new JsonFile(__DIR__.'/Fixtures/tabs2.json');
|
||||
$data = $jsonFile->read();
|
||||
$jsonFile->write(['foo' => 'baz']);
|
||||
|
||||
self::assertSame("{\n\t\"foo\": \"baz\"\n}\n", file_get_contents(__DIR__.'/Fixtures/tabs2.json'));
|
||||
|
||||
unlink(__DIR__.'/Fixtures/tabs2.json');
|
||||
}
|
||||
|
||||
public function testOverwritesIndentationByDefault(): void
|
||||
{
|
||||
copy(__DIR__.'/Fixtures/tabs.json', __DIR__.'/Fixtures/tabs2.json');
|
||||
$jsonFile = new JsonFile(__DIR__.'/Fixtures/tabs2.json');
|
||||
$jsonFile->write(['foo' => 'baz']);
|
||||
|
||||
self::assertSame("{\n \"foo\": \"baz\"\n}\n", file_get_contents(__DIR__.'/Fixtures/tabs2.json'));
|
||||
|
||||
unlink(__DIR__.'/Fixtures/tabs2.json');
|
||||
}
|
||||
|
||||
private function expectParseException(string $text, string $json): void
|
||||
{
|
||||
try {
|
||||
|
|
Loading…
Reference in New Issue