Completed
Push — master ( d41cf1...36fce9 )
by Javi
23:31
created

ResponseTransformer::transform()   B

Complexity

Conditions 8
Paths 7

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 7.1428
c 0
b 0
f 0
cc 8
eloc 12
nc 7
nop 1
1
<?php
2
3
namespace Philae\Middlewares;
4
5
use Interop\Http\ServerMiddleware\DelegateInterface;
6
use Middlewares\Utils;
7
use Psr\Http\Message\ResponseInterface;
8
use Psr\Http\Message\ServerRequestInterface;
9
10
/**
11
 * Wraps the request handler callback in another one that will
12
 * try to convert the request handler result into a PSR-7 Response
13
 * and/or apply some changes to the response object itself
14
 * (like setting/fixing the Content Length header).
15
 */
16
class ResponseTransformer extends AbstractMiddleware
17
{
18
    /**
19
     * @var string Attribute name for handler reference
20
     */
21
    protected $handlerAttribute = 'request-handler';
22
23
    /**
24
     * Set the attribute name to store handler reference.
25
     *
26
     * @param string $handlerAttribute
27
     *
28
     * @return self
29
     */
30
    public function handlerAttribute(string $handlerAttribute)
31
    {
32
        $this->handlerAttribute = $handlerAttribute;
33
34
        return $this;
35
    }
36
37
    /**
38
     * Process a server request and return a response.
39
     *
40
     * @param ServerRequestInterface $request
41
     * @param DelegateInterface $delegate
42
     *
43
     * @return ResponseInterface
44
     */
45
    public function process(ServerRequestInterface $request, DelegateInterface $delegate)
46
    {
47
        $handler = $request->getAttribute($this->handlerAttribute);
48
49
        if (!is_callable($handler)) {
50
            return $delegate->process($request);
51
        }
52
53
        $handlerWrapper = function (...$args) use ($handler) {
54
            $result = call_user_func($handler, ...$args);
55
56
            $response = $this->transform($result);
57
58
            if (!($response instanceof ResponseInterface)) {
59
                $type = is_object($response) ? get_class($response) : gettype($response);
60
                throw new \UnexpectedValueException(
61
                    'Cannot convert the request handler result of type `' . $type . '` into a Response object.'
62
                );
63
            }
64
65
            return $response;
66
        };
67
68
        $request = $request->withAttribute($this->handlerAttribute, $handlerWrapper);
69
70
        return $delegate->process($request);
71
    }
72
73
    /**
74
     * Tries to transform the given result into a Response object, otherwise it is returned back.
75
     * @param mixed $result
76
     * @return ResponseInterface|mixed
77
     */
78
    public function transform($result)
79
    {
80
        if ($result instanceof ResponseInterface) {
81
            return $result->withHeader('Content-Length', $result->getBody()->getSize());
82
        }
83
84
        if (is_scalar($result) || is_null($result)) {
85
            $result = strval($result);
86
        } elseif (is_object($result) && method_exists($result, '__toString')) {
87
            $result = $result->__toString();
88
        }
89
90
        if (!is_string($result)) {
91
            return $result;
92
        }
93
94
        $response = Utils\Factory::createResponse((strlen($result) > 0) ? 200 : 204);
95
        $response->getBody()->write($result);
96
97
        return $response;
98
    }
99
}
100