|  | 
| 14 | 14 | use GraphQL\Utils\AST; | 
| 15 | 15 | use GraphQL\Utils\Utils; | 
| 16 | 16 | use GraphQL\Validator\DocumentValidator; | 
|  | 17 | +use Psr\Http\Message\ResponseInterface; | 
| 17 | 18 | use Psr\Http\Message\ServerRequestInterface; | 
|  | 19 | +use Psr\Http\Message\StreamInterface; | 
| 18 | 20 | 
 | 
| 19 | 21 | /** | 
| 20 | 22 |  * Class Helper | 
| @@ -131,7 +133,9 @@ private function promiseToExecuteOperation(PromiseAdapter $promiseAdapter, Serve | 
| 131 | 133 |                     return FormattedError::createFromException($e, true); | 
| 132 | 134 |                 }; | 
| 133 | 135 |             } else { | 
| 134 |  | -                $errorFormatter = $config->getErrorFormatter(); | 
|  | 136 | +                $errorFormatter = $config->getErrorFormatter() ?: function($e) { | 
|  | 137 | +                    return FormattedError::createFromException($e, false); | 
|  | 138 | +                }; | 
| 135 | 139 |             } | 
| 136 | 140 |             $result->setErrorFormatter($errorFormatter); | 
| 137 | 141 |             return $result; | 
| @@ -264,6 +268,66 @@ public function parsePsrRequest(ServerRequestInterface $request) | 
| 264 | 268 |         ); | 
| 265 | 269 |     } | 
| 266 | 270 | 
 | 
|  | 271 | +    /** | 
|  | 272 | +     * Converts query execution result to PSR response | 
|  | 273 | +     * | 
|  | 274 | +     * @param Promise|ExecutionResult|ExecutionResult[] $result | 
|  | 275 | +     * @param ResponseInterface $response | 
|  | 276 | +     * @param StreamInterface $writableBodyStream | 
|  | 277 | +     * @return Promise|ResponseInterface | 
|  | 278 | +     */ | 
|  | 279 | +    public function toPsrResponse($result, ResponseInterface $response, StreamInterface $writableBodyStream) | 
|  | 280 | +    { | 
|  | 281 | +        if ($result instanceof Promise) { | 
|  | 282 | +            return $result->then(function($actualResult) use ($response, $writableBodyStream) { | 
|  | 283 | +                return $this->doConvertToPsrResponse($actualResult, $response, $writableBodyStream); | 
|  | 284 | +            }); | 
|  | 285 | +        } else { | 
|  | 286 | +            return $this->doConvertToPsrResponse($result, $response, $writableBodyStream); | 
|  | 287 | +        } | 
|  | 288 | +    } | 
|  | 289 | + | 
|  | 290 | +    private function doConvertToPsrResponse($result, ResponseInterface $response, StreamInterface $writableBodyStream) | 
|  | 291 | +    { | 
|  | 292 | +        $httpStatus = $this->resolveHttpStatus($result); | 
|  | 293 | + | 
|  | 294 | +        $result = json_encode($result); | 
|  | 295 | +        $writableBodyStream->write($result); | 
|  | 296 | + | 
|  | 297 | +        return $response | 
|  | 298 | +            ->withStatus($httpStatus) | 
|  | 299 | +            ->withHeader('Content-Type', 'application/json') | 
|  | 300 | +            ->withBody($writableBodyStream); | 
|  | 301 | +    } | 
|  | 302 | + | 
|  | 303 | +    /** | 
|  | 304 | +     * @param Promise|ExecutionResult|ExecutionResult[] $result | 
|  | 305 | +     * @param bool $exitWhenDone | 
|  | 306 | +     */ | 
|  | 307 | +    public function sendResponse($result, $exitWhenDone = false) | 
|  | 308 | +    { | 
|  | 309 | +        if ($result instanceof Promise) { | 
|  | 310 | +            $result->then(function($actualResult) use ($exitWhenDone) { | 
|  | 311 | +                $this->doSendResponse($actualResult, $exitWhenDone); | 
|  | 312 | +            }); | 
|  | 313 | +        } else { | 
|  | 314 | +            $this->doSendResponse($result, $exitWhenDone); | 
|  | 315 | +        } | 
|  | 316 | +    } | 
|  | 317 | + | 
|  | 318 | +    private function doSendResponse($result, $exitWhenDone) | 
|  | 319 | +    { | 
|  | 320 | +        $httpStatus = $this->resolveHttpStatus($result); | 
|  | 321 | +        $body = json_encode($result); | 
|  | 322 | + | 
|  | 323 | +        header('Content-Type: application/json', true, $httpStatus); | 
|  | 324 | +        echo $body; | 
|  | 325 | + | 
|  | 326 | +        if ($exitWhenDone) { | 
|  | 327 | +            exit; | 
|  | 328 | +        } | 
|  | 329 | +    } | 
|  | 330 | + | 
| 267 | 331 |     /** | 
| 268 | 332 |      * Parses normalized request params and returns instance of OperationParams or array of OperationParams in | 
| 269 | 333 |      * case of batch operation. | 
| @@ -347,4 +411,39 @@ public function validateOperationParams(OperationParams $params) | 
| 347 | 411 |         } | 
| 348 | 412 |         return $errors; | 
| 349 | 413 |     } | 
|  | 414 | + | 
|  | 415 | +    /** | 
|  | 416 | +     * @param $result | 
|  | 417 | +     * @return int | 
|  | 418 | +     */ | 
|  | 419 | +    private function resolveHttpStatus($result) | 
|  | 420 | +    { | 
|  | 421 | +        if (is_array($result)) { | 
|  | 422 | +            Utils::each($tmp, function ($executionResult, $index) { | 
|  | 423 | +                if (!$executionResult instanceof ExecutionResult) { | 
|  | 424 | +                    throw new InvariantViolation(sprintf( | 
|  | 425 | +                        "Expecting every entry of batched query result to be instance of %s but entry at position %d is %s", | 
|  | 426 | +                        ExecutionResult::class, | 
|  | 427 | +                        $index, | 
|  | 428 | +                        Utils::printSafe($executionResult) | 
|  | 429 | +                    )); | 
|  | 430 | +                } | 
|  | 431 | +            }); | 
|  | 432 | +            $httpStatus = 200; | 
|  | 433 | +        } else { | 
|  | 434 | +            if (!$result instanceof ExecutionResult) { | 
|  | 435 | +                throw new InvariantViolation(sprintf( | 
|  | 436 | +                    "Expecting query result to be instance of %s but got %s", | 
|  | 437 | +                    ExecutionResult::class, | 
|  | 438 | +                    Utils::printSafe($result) | 
|  | 439 | +                )); | 
|  | 440 | +            } | 
|  | 441 | +            if ($result->data === null && !empty($result->errors)) { | 
|  | 442 | +                $httpStatus = 400; | 
|  | 443 | +            } else { | 
|  | 444 | +                $httpStatus = 200; | 
|  | 445 | +            } | 
|  | 446 | +        } | 
|  | 447 | +        return $httpStatus; | 
|  | 448 | +    } | 
| 350 | 449 | } | 
0 commit comments