88
99namespace Microsoft \Graph \Core \Requests ;
1010
11+ use Exception ;
1112use GuzzleHttp \Psr7 \Utils ;
1213use InvalidArgumentException ;
13- use Microsoft \Kiota \Abstractions \RequestInformation ;
1414use Microsoft \Kiota \Abstractions \Serialization \Parsable ;
1515use Microsoft \Kiota \Abstractions \Serialization \ParseNode ;
1616use Microsoft \Kiota \Abstractions \Serialization \ParseNodeFactory ;
1717use Microsoft \Kiota \Abstractions \Serialization \ParseNodeFactoryRegistry ;
1818use Microsoft \Kiota \Abstractions \Serialization \SerializationWriter ;
19- use Microsoft \Kiota \Serialization \Json \JsonParseNodeFactory ;
2019use RuntimeException ;
21- use UnexpectedValueException ;
2220
2321/**
2422 * Class BatchResponseContent
@@ -71,15 +69,15 @@ public function getResponse(string $requestId): BatchResponseItem
7169 }
7270
7371 /**
74- * Deserializes a response item's body to $type. $type MUST implement Parsable
72+ * Deserializes a response item's body to $type. $type MUST implement Parsable.
73+ * Uses the ParseNodeFactory registry to get the required Parse Node implementation
7574 *
7675 * @template T of Parsable
7776 * @param string $requestId
7877 * @param class-string<T> $type Parsable class name
79- * @param ParseNodeFactory|null $parseNodeFactory checks the ParseNodeFactoryRegistry by default
8078 * @return T|null
8179 */
82- public function getResponseBody (string $ requestId , string $ type, ? ParseNodeFactory $ parseNodeFactory = null ): ?Parsable
80+ public function getResponseBody (string $ requestId , string $ type ): ?Parsable
8381 {
8482 if (!$ this ->responses || !array_key_exists ($ requestId , $ this ->responses )) {
8583 throw new InvalidArgumentException ("No response found for id: {$ requestId }" );
@@ -94,17 +92,25 @@ public function getResponseBody(string $requestId, string $type, ?ParseNodeFacto
9492 throw new RuntimeException ("Unable to get content-type header in response item " );
9593 }
9694 $ responseBody = $ response ->getBody () ?? Utils::streamFor (null );
97- if ($ parseNodeFactory ) {
98- $ parseNode = $ parseNodeFactory ->getRootParseNode ($ contentType , $ responseBody );
99- } else {
100- // Check the registry or default to Json deserialization
95+ try {
10196 try {
10297 $ parseNode = ParseNodeFactoryRegistry::getDefaultInstance ()->getRootParseNode ($ contentType , $ responseBody );
103- } catch (UnexpectedValueException $ ex ) {
104- $ parseNode = (new JsonParseNodeFactory ())->getRootParseNode ($ contentType , $ responseBody );
98+ } catch (Exception $ ex ) {
99+ // Responses to requests with base 64 encoded stream bodies are base 64 encoded
100+ // Tries to decode the response body and retries deserialization
101+ $ responseBody ->rewind ();
102+ $ base64DecodedBody = Utils::streamFor (base64_decode ($ responseBody ->getContents ()));
103+ $ parseNode = ParseNodeFactoryRegistry::getDefaultInstance ()
104+ ->getRootParseNode ($ contentType , $ base64DecodedBody );
105+ // Update response body only after we're sure decoding worked
106+ $ response ->setBody ($ base64DecodedBody );
105107 }
108+ return $ parseNode ->getObjectValue ([$ type , 'createFromDiscriminatorValue ' ]);
109+ } catch (Exception $ ex ) {
110+ throw new InvalidArgumentException (
111+ "Unable to deserialize batch response for request Id: $ requestId to $ type "
112+ );
106113 }
107- return $ parseNode ->getObjectValue ([$ type , 'createFromDiscriminatorValue ' ]);
108114 }
109115
110116 public function getFieldDeserializers (): array
0 commit comments