CreatedResourceRenderer::render()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 13
dl 0
loc 19
rs 9.8333
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BEAR\Package\Provide\Representation;
6
7
use BEAR\Package\Exception\LocationHeaderRequestException;
8
use BEAR\Resource\RenderInterface;
9
use BEAR\Resource\ResourceInterface;
10
use BEAR\Resource\ResourceObject;
11
use BEAR\Sunday\Extension\Router\RouterInterface;
12
use Override;
13
use Throwable;
14
15
use function is_string;
16
use function parse_str;
17
use function parse_url;
18
use function sprintf;
19
20
use const PHP_URL_HOST;
21
use const PHP_URL_PATH;
22
use const PHP_URL_QUERY;
23
use const PHP_URL_SCHEME;
24
25
/**
26
 * 201 CreatedResource renderer
27
 */
28
final class CreatedResourceRenderer implements RenderInterface
29
{
30
    public function __construct(
31
        private RouterInterface $router,
32
        private ResourceInterface $resource,
33
    ) {
34
    }
35
36
    /**
37
     * {@inheritDoc}
38
     */
39
    #[Override]
40
    public function render(ResourceObject $ro)
41
    {
42
        $urlSchema = (string) parse_url((string) $ro->uri, PHP_URL_SCHEME);
43
        $urlHost = (string) parse_url((string) $ro->uri, PHP_URL_HOST);
44
        $locationUri = sprintf('%s://%s%s', $urlSchema, $urlHost, $ro->headers['Location']);
45
        try {
46
            $locatedResource = $this->resource->uri($locationUri)();
47
        } catch (Throwable $e) {
48
            $ro->code = 500;
49
            $ro->view = '';
50
51
            throw new LocationHeaderRequestException($locationUri, 0, $e);
52
        }
53
54
        $this->updateHeaders($ro);
55
        $ro->view = $locatedResource->toString();
56
57
        return $ro->view;
58
    }
59
60
    private function getReverseMatchedLink(string $uri): string
61
    {
62
        $routeName = (string) parse_url($uri, PHP_URL_PATH);
63
        $urlQuery = (string) parse_url($uri, PHP_URL_QUERY);
64
        $urlQuery ? parse_str($urlQuery, $value) : $value = [];
65
        if ($value === []) {
66
            return $uri;
67
        }
68
69
        /** @var array<string, mixed> $value */
70
        $reverseUri = $this->router->generate($routeName, $value);
71
        if (is_string($reverseUri)) {
72
            return $reverseUri;
73
        }
74
75
        return $uri;
76
    }
77
78
    private function updateHeaders(ResourceObject $ro): void
79
    {
80
        $ro->headers['content-type'] = 'application/hal+json';
81
        if (! isset($ro->headers['Location'])) {
82
            // @codeCoverageIgnoreStart
83
            return;
84
            // @codeCoverageIgnoreEnd
85
        }
86
87
        $ro->headers['Location'] = $this->getReverseMatchedLink($ro->headers['Location']);
88
    }
89
}
90