CreatedResourceRenderer::updateHeaders()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 10
rs 10
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\Package\Types;
9
use BEAR\Resource\RenderInterface;
10
use BEAR\Resource\ResourceInterface;
11
use BEAR\Resource\ResourceObject;
12
use BEAR\Sunday\Extension\Router\RouterInterface;
13
use Override;
14
use Throwable;
15
16
use function is_string;
17
use function parse_str;
18
use function parse_url;
19
use function sprintf;
20
21
use const PHP_URL_HOST;
22
use const PHP_URL_PATH;
23
use const PHP_URL_QUERY;
24
use const PHP_URL_SCHEME;
25
26
/**
27
 * 201 CreatedResource renderer
28
 *
29
 * @psalm-import-type QueryParams from Types
30
 */
31
final class CreatedResourceRenderer implements RenderInterface
32
{
33
    public function __construct(
34
        private RouterInterface $router,
35
        private ResourceInterface $resource,
36
    ) {
37
    }
38
39
    /**
40
     * {@inheritDoc}
41
     */
42
    #[Override]
43
    public function render(ResourceObject $ro)
44
    {
45
        $urlSchema = (string) parse_url((string) $ro->uri, PHP_URL_SCHEME);
46
        $urlHost = (string) parse_url((string) $ro->uri, PHP_URL_HOST);
47
        $locationUri = sprintf('%s://%s%s', $urlSchema, $urlHost, $ro->headers['Location']);
48
        try {
49
            $locatedResource = $this->resource->uri($locationUri)();
50
        } catch (Throwable $e) {
51
            $ro->code = 500;
52
            $ro->view = '';
53
54
            throw new LocationHeaderRequestException($locationUri, 0, $e);
55
        }
56
57
        $this->updateHeaders($ro);
58
        $ro->view = $locatedResource->toString();
59
60
        return $ro->view;
61
    }
62
63
    private function getReverseMatchedLink(string $uri): string
64
    {
65
        $routeName = (string) parse_url($uri, PHP_URL_PATH);
66
        $urlQuery = (string) parse_url($uri, PHP_URL_QUERY);
67
        $urlQuery ? parse_str($urlQuery, $value) : $value = [];
68
        if ($value === []) {
69
            return $uri;
70
        }
71
72
        /** @var QueryParams $value */
73
        $reverseUri = $this->router->generate($routeName, $value);
0 ignored issues
show
Bug introduced by
$value of type BEAR\Package\Provide\Representation\QueryParams is incompatible with the type array<string,mixed> expected by parameter $data of BEAR\Sunday\Extension\Ro...erInterface::generate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

73
        $reverseUri = $this->router->generate($routeName, /** @scrutinizer ignore-type */ $value);
Loading history...
74
        if (is_string($reverseUri)) {
75
            return $reverseUri;
76
        }
77
78
        return $uri;
79
    }
80
81
    private function updateHeaders(ResourceObject $ro): void
82
    {
83
        $ro->headers['content-type'] = 'application/hal+json';
84
        if (! isset($ro->headers['Location'])) {
85
            // @codeCoverageIgnoreStart
86
            return;
87
            // @codeCoverageIgnoreEnd
88
        }
89
90
        $ro->headers['Location'] = $this->getReverseMatchedLink($ro->headers['Location']);
91
    }
92
}
93