Passed
Push — master ( 9013bb...125cf1 )
by Kirill
03:56
created

CallableHandler::wrapResponse()   A

Complexity

Conditions 6
Paths 4

Size

Total Lines 20
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 10
c 1
b 0
f 0
dl 0
loc 20
rs 9.2222
cc 6
nc 4
nop 3
1
<?php
2
3
/**
4
 * Spiral Framework.
5
 *
6
 * @license   MIT
7
 * @author    Anton Titov (Wolfy-J)
8
 */
9
10
declare(strict_types=1);
11
12
namespace Spiral\Http;
13
14
use Psr\Http\Message\ResponseFactoryInterface;
15
use Psr\Http\Message\ResponseInterface as Response;
16
use Psr\Http\Message\ServerRequestInterface as Request;
17
use Psr\Http\Server\RequestHandlerInterface;
18
use Spiral\Http\Traits\JsonTrait;
19
20
/**
21
 * Provides ability to invoke any handler and write it's response into ResponseInterface.
22
 */
23
final class CallableHandler implements RequestHandlerInterface
24
{
25
    use JsonTrait;
26
27
    /** @var callable */
28
    private $callable;
29
30
    /** @var ResponseFactoryInterface */
31
    private $responseFactory;
32
33
    /**
34
     * @param callable                 $callable
35
     * @param ResponseFactoryInterface $responseFactory
36
     */
37
    public function __construct(callable $callable, ResponseFactoryInterface $responseFactory)
38
    {
39
        $this->callable = $callable;
40
        $this->responseFactory = $responseFactory;
41
    }
42
43
    /**
44
     * @inheritdoc
45
     */
46
    public function handle(Request $request): Response
47
    {
48
        $outputLevel = ob_get_level();
49
        ob_start();
50
51
        $output = $result = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
52
53
        $response = $this->responseFactory->createResponse(200);
54
        try {
55
            $result = ($this->callable)($request, $response);
56
        } catch (\Throwable $e) {
57
            ob_get_clean();
58
            throw $e;
59
        } finally {
60
            while (ob_get_level() > $outputLevel + 1) {
61
                $output = ob_get_clean() . $output;
62
            }
63
        }
64
65
        return $this->wrapResponse(
66
            $response,
67
            $result,
68
            ob_get_clean() . $output
69
        );
70
    }
71
72
    /**
73
     * Convert endpoint result into valid response.
74
     *
75
     * @param Response $response Initial pipeline response.
76
     * @param mixed    $result   Generated endpoint output.
77
     * @param string   $output   Buffer output.
78
79
     * @return Response
80
     */
81
    private function wrapResponse(Response $response, $result = null, string $output = ''): Response
82
    {
83
        if ($result instanceof Response) {
84
            if (!empty($output) && $result->getBody()->isWritable()) {
85
                $result->getBody()->write($output);
86
            }
87
88
            return $result;
89
        }
90
91
        if (is_array($result) || $result instanceof \JsonSerializable) {
92
            $response = $this->writeJson($response, $result);
93
        } else {
94
            $response->getBody()->write((string)$result);
95
        }
96
97
        //Always glue buffered output
98
        $response->getBody()->write($output);
99
100
        return $response;
101
    }
102
}
103