diff --git a/src/Illuminate/View/Compilers/Concerns/CompilesJson.php b/src/Illuminate/View/Compilers/Concerns/CompilesJson.php index cf343e972c10..e4c34bc68d4c 100644 --- a/src/Illuminate/View/Compilers/Concerns/CompilesJson.php +++ b/src/Illuminate/View/Compilers/Concerns/CompilesJson.php @@ -19,12 +19,83 @@ trait CompilesJson */ protected function compileJson($expression) { - $parts = explode(',', $this->stripParentheses($expression)); + [$data, $options, $depth] = $this->parseArguments($this->stripParentheses($expression)) + ['null', $this->encodingOptions, 512]; - $options = isset($parts[1]) ? trim($parts[1]) : $this->encodingOptions; + return ""; + } + + /** + * Parse arguments from an expression, respecting nested structures. + * + * This method properly handles commas inside arrays, closures, function calls, + * and other nested structures by using PHP's tokenizer. + * + * @param string $expression + * @return array{0?: string, 1?: string, 2?: string} + */ + protected function parseArguments($expression) + { + if ('' === trim($expression)) { + return []; + } + + $tokens = @token_get_all(' $token) { + // Skip the initial "; + return $parts; } } diff --git a/tests/View/Blade/BladeJsonTest.php b/tests/View/Blade/BladeJsonTest.php index bdfab95ef375..3397e37fbe87 100644 --- a/tests/View/Blade/BladeJsonTest.php +++ b/tests/View/Blade/BladeJsonTest.php @@ -19,4 +19,53 @@ public function testEncodingOptionsCanBeOverwritten() $this->assertEquals($expected, $this->compiler->compileString($string)); } + + public function testJsonWithComplexArrayContainingNestedStructures() + { + $string = '@json([\'items\' => collect([1, 2, 3])->map(fn($x) => [\'id\' => $x, \'name\' => "test"]), \'translation\' => \'%:booking.benefits%\'])'; + $expected = ' collect([1, 2, 3])->map(fn($x) => [\'id\' => $x, \'name\' => "test"]), \'translation\' => \'%:booking.benefits%\'], 15, 512) ?>'; + + $this->assertEquals($expected, $this->compiler->compileString($string)); + } + + public function testJsonWithArrayContainingMultipleCommas() + { + $string = '@json([\'a\' => 1, \'b\' => 2, \'c\' => 3], JSON_PRETTY_PRINT)'; + $expected = ' 1, \'b\' => 2, \'c\' => 3], JSON_PRETTY_PRINT, 512) ?>'; + + $this->assertEquals($expected, $this->compiler->compileString($string)); + } + + public function testJsonWithClosureContainingCommas() + { + $string = '@json($items->map(fn($item) => [\'icon\' => $item->icon, \'title\' => (string)$item->title, \'description\' => (string)$item->description]))'; + $expected = 'map(fn($item) => [\'icon\' => $item->icon, \'title\' => (string)$item->title, \'description\' => (string)$item->description]), 15, 512) ?>'; + + $this->assertEquals($expected, $this->compiler->compileString($string)); + } + + public function testJsonWithAllThreeArguments() + { + $string = '@json($data, JSON_PRETTY_PRINT, 256)'; + $expected = ''; + + $this->assertEquals($expected, $this->compiler->compileString($string)); + } + + public function testJsonWithEmptyExpressionDefaultsToNull() + { + $string = '@json()'; + $expected = ''; + + $this->assertEquals($expected, $this->compiler->compileString($string)); + } + + public function testJsonWithIssue56331ExactCase() + { + // This is the exact case from GitHub issue #56331 + $string = '@json([\'items\' => $helpers[\'benefit\'][\'getAll\']()->map(fn($item) => [\'icon\' => $item->icon, \'title\' => (string)$item->title, \'description\' => (string)$item->description]), \'translation\' => \'%:booking.benefits%\'])'; + $expected = ' $helpers[\'benefit\'][\'getAll\']()->map(fn($item) => [\'icon\' => $item->icon, \'title\' => (string)$item->title, \'description\' => (string)$item->description]), \'translation\' => \'%:booking.benefits%\'], 15, 512) ?>'; + + $this->assertEquals($expected, $this->compiler->compileString($string)); + } }