From dd219822a700e80c3a407d1fe29eb8a400771168 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Nov 2025 17:19:42 +0000 Subject: [PATCH 1/2] Initial plan From a4014413e935381907548baba4844f02f6ebe61f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Nov 2025 17:24:32 +0000 Subject: [PATCH 2/2] Fix batch response decoding error - check if regex match exists before accessing Co-authored-by: anderly <573151+anderly@users.noreply.github.com> --- src/ODataResponse.php | 5 +- tests/BatchResponseTest.php | 158 ++++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 tests/BatchResponseTest.php diff --git a/src/ODataResponse.php b/src/ODataResponse.php index 6671618..79598e3 100644 --- a/src/ODataResponse.php +++ b/src/ODataResponse.php @@ -90,8 +90,9 @@ private function decodeBody() $decodedBody = json_decode($this->body, true, 512, JSON_BIGINT_AS_STRING); if ($decodedBody === null) { $matches = null; - preg_match('~\{(?:[^{}]|(?R))*\}~', $this->body, $matches); - $decodedBody = json_decode($matches[0], true, 512, JSON_BIGINT_AS_STRING); + if (preg_match('~\{(?:[^{}]|(?R))*\}~', $this->body, $matches)) { + $decodedBody = json_decode($matches[0], true, 512, JSON_BIGINT_AS_STRING); + } if ($decodedBody === null) { $decodedBody = array(); } diff --git a/tests/BatchResponseTest.php b/tests/BatchResponseTest.php new file mode 100644 index 0000000..588ec89 --- /dev/null +++ b/tests/BatchResponseTest.php @@ -0,0 +1,158 @@ +createMock(ODataRequest::class); + + // This should not throw an exception + $response = new ODataResponse($request, $batchResponseBody, 200, []); + + // The response should be created successfully + $this->assertTrue(true, "ODataResponse should handle batch responses without crashing"); + + // The body should be decoded to at least an empty array (no crash) + $body = $response->getBody(); + $this->assertIsArray($body); + } + + /** + * Test that responses with no JSON content don't crash + */ + public function testResponseWithNoJsonContent() + { + $nonJsonResponse = "This is plain text with no JSON at all"; + + $request = $this->createMock(ODataRequest::class); + + // This should not throw an exception + $response = new ODataResponse($request, $nonJsonResponse, 200, []); + + // The body should be decoded to an empty array + $body = $response->getBody(); + $this->assertIsArray($body); + $this->assertEquals([], $body); + } + + /** + * Test that responses with embedded JSON still work + */ + public function testResponseWithEmbeddedJson() + { + $responseWithEmbeddedJson = 'Some text before {"value": "test"} some text after'; + + $request = $this->createMock(ODataRequest::class); + + // This should not throw an exception + $response = new ODataResponse($request, $responseWithEmbeddedJson, 200, []); + + // The body should extract the JSON portion + $body = $response->getBody(); + $this->assertIsArray($body); + $this->assertEquals('test', $body['value']); + } + + /** + * Test normal JSON response still works correctly + */ + public function testNormalJsonResponse() + { + $jsonResponse = json_encode(['value' => 'test', 'count' => 5]); + + $request = $this->createMock(ODataRequest::class); + $response = new ODataResponse($request, $jsonResponse, 200, []); + + $body = $response->getBody(); + $this->assertIsArray($body); + $this->assertEquals('test', $body['value']); + $this->assertEquals(5, $body['count']); + } +} + +// If running standalone (not via PHPUnit), execute the tests +if (!class_exists('PHPUnit\Framework\TestCase') && basename(__FILE__) === basename($_SERVER['PHP_SELF'])) { + echo "Running BatchResponse tests...\n\n"; + + $test = new BatchResponseTest(); + $methods = [ + 'testBatchResponseWithMultipartContent', + 'testResponseWithNoJsonContent', + 'testResponseWithEmbeddedJson', + 'testNormalJsonResponse' + ]; + + foreach ($methods as $method) { + try { + echo "Running $method... "; + $test->$method(); + echo "✓ PASSED\n"; + } catch (\Exception $e) { + echo "✗ FAILED: " . $e->getMessage() . "\n"; + } + } + + echo "\nTests completed.\n"; +}