Skip to content

Commit a255929

Browse files
Copilotanderly
andauthored
Fix ODataResponse to handle non-array values in "value" key (#184)
* Initial plan * Fix ODataResponse to handle non-array values in 'value' key Co-authored-by: anderly <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: anderly <[email protected]>
1 parent 35d6ed5 commit a255929

File tree

2 files changed

+156
-4
lines changed

2 files changed

+156
-4
lines changed

src/ODataResponse.php

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,19 @@ public function getResponseAsObject($returnType)
153153

154154
//If more than one object is returned
155155
if (array_key_exists(Constants::ODATA_VALUE, $result)) {
156-
$objArray = array();
157-
foreach ($result[Constants::ODATA_VALUE] as $obj) {
158-
$objArray[] = new $class($obj);
156+
$value = $result[Constants::ODATA_VALUE];
157+
158+
// Check if value is an array before iterating
159+
if (is_array($value)) {
160+
$objArray = array();
161+
foreach ($value as $obj) {
162+
$objArray[] = new $class($obj);
163+
}
164+
return $objArray;
165+
} else {
166+
// Single value case - wrap in array and create single object
167+
return [new $class(['value' => $value])];
159168
}
160-
return $objArray;
161169
} else {
162170
return [new $class($result)];
163171
}

tests/ODataResponseTest.php

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
<?php
2+
3+
namespace SaintSystems\OData\Tests;
4+
5+
// If running standalone, load autoloader
6+
if (basename(__FILE__) === basename($_SERVER['PHP_SELF'])) {
7+
require_once __DIR__ . '/../vendor/autoload.php';
8+
}
9+
10+
use SaintSystems\OData\Entity;
11+
use SaintSystems\OData\ODataResponse;
12+
use SaintSystems\OData\ODataRequest;
13+
14+
// Check if PHPUnit is available, if not provide a fallback
15+
if (class_exists('PHPUnit\Framework\TestCase')) {
16+
class ODataResponseTestBase extends \PHPUnit\Framework\TestCase {}
17+
} else {
18+
// Fallback base class for when PHPUnit is not available
19+
class ODataResponseTestBase {
20+
protected function createMock($className) {
21+
return new \stdClass();
22+
}
23+
protected function assertIsArray($value) {
24+
if (!is_array($value)) throw new \Exception("Expected array");
25+
}
26+
protected function assertCount($expected, $array) {
27+
if (count($array) !== $expected) throw new \Exception("Count mismatch");
28+
}
29+
protected function assertInstanceOf($class, $object) {
30+
if (!($object instanceof $class)) throw new \Exception("Instance mismatch");
31+
}
32+
}
33+
}
34+
35+
class ODataResponseTest extends ODataResponseTestBase
36+
{
37+
public function testGetResponseAsObjectWithArrayValue()
38+
{
39+
// Test case for traditional array response
40+
$responseBody = json_encode([
41+
'value' => [
42+
['id' => 1, 'name' => 'Test 1'],
43+
['id' => 2, 'name' => 'Test 2']
44+
]
45+
]);
46+
47+
$request = $this->createMock(ODataRequest::class);
48+
$response = new ODataResponse($request, $responseBody, 200, []);
49+
50+
$result = $response->getResponseAsObject(Entity::class);
51+
52+
$this->assertIsArray($result);
53+
$this->assertCount(2, $result);
54+
$this->assertInstanceOf(Entity::class, $result[0]);
55+
$this->assertInstanceOf(Entity::class, $result[1]);
56+
}
57+
58+
public function testGetResponseAsObjectWithStringValue()
59+
{
60+
// Test case for single string value response (the reported issue)
61+
$responseBody = json_encode([
62+
'value' => 'uniqueIDofCreatedOrder'
63+
]);
64+
65+
$request = $this->createMock(ODataRequest::class);
66+
$response = new ODataResponse($request, $responseBody, 200, []);
67+
68+
$result = $response->getResponseAsObject(Entity::class);
69+
70+
$this->assertIsArray($result);
71+
$this->assertCount(1, $result);
72+
$this->assertInstanceOf(Entity::class, $result[0]);
73+
74+
// Verify the value is properly stored
75+
$entity = $result[0];
76+
$properties = $entity->getProperties();
77+
if (!isset($properties['value']) || $properties['value'] !== 'uniqueIDofCreatedOrder') {
78+
throw new \Exception("Value not properly stored in Entity");
79+
}
80+
}
81+
82+
public function testGetResponseAsObjectWithNumericValue()
83+
{
84+
// Test case for single numeric value response
85+
$responseBody = json_encode([
86+
'value' => 12345
87+
]);
88+
89+
$request = $this->createMock(ODataRequest::class);
90+
$response = new ODataResponse($request, $responseBody, 200, []);
91+
92+
$result = $response->getResponseAsObject(Entity::class);
93+
94+
$this->assertIsArray($result);
95+
$this->assertCount(1, $result);
96+
$this->assertInstanceOf(Entity::class, $result[0]);
97+
98+
// Verify the value is properly stored
99+
$entity = $result[0];
100+
$properties = $entity->getProperties();
101+
if (!isset($properties['value']) || $properties['value'] !== 12345) {
102+
throw new \Exception("Numeric value not properly stored in Entity");
103+
}
104+
}
105+
106+
public function testGetResponseAsObjectWithoutValueKey()
107+
{
108+
// Test case for response without "value" key
109+
$responseBody = json_encode([
110+
'id' => 1,
111+
'name' => 'Test'
112+
]);
113+
114+
$request = $this->createMock(ODataRequest::class);
115+
$response = new ODataResponse($request, $responseBody, 200, []);
116+
117+
$result = $response->getResponseAsObject(Entity::class);
118+
119+
$this->assertIsArray($result);
120+
$this->assertCount(1, $result);
121+
$this->assertInstanceOf(Entity::class, $result[0]);
122+
}
123+
}
124+
125+
// If running standalone (not via PHPUnit), execute the tests
126+
if (!class_exists('PHPUnit\Framework\TestCase') && basename(__FILE__) === basename($_SERVER['PHP_SELF'])) {
127+
echo "Running ODataResponse tests...\n\n";
128+
129+
$test = new ODataResponseTest();
130+
$methods = ['testGetResponseAsObjectWithArrayValue', 'testGetResponseAsObjectWithStringValue',
131+
'testGetResponseAsObjectWithNumericValue', 'testGetResponseAsObjectWithoutValueKey'];
132+
133+
foreach ($methods as $method) {
134+
try {
135+
echo "Running $method... ";
136+
$test->$method();
137+
echo "✓ PASSED\n";
138+
} catch (Exception $e) {
139+
echo "✗ FAILED: " . $e->getMessage() . "\n";
140+
}
141+
}
142+
143+
echo "\nTests completed.\n";
144+
}

0 commit comments

Comments
 (0)