Completed
Push — 1.x ( 68b709...d41c3b )
by Akihito
15s queued 11s
created

HalRenderer   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 105
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 78%

Importance

Changes 0
Metric Value
wmc 16
lcom 1
cbo 4
dl 0
loc 105
ccs 39
cts 50
cp 0.78
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A render() 0 7 1
A renderHal() 0 11 2
A valuateElements() 0 18 4
A isDifferentSchema() 0 4 1
A getReverseMatchedLink() 0 4 1
A getHal() 0 9 2
A valuate() 0 8 2
A updateHeaders() 0 7 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BEAR\Resource;
6
7
use BEAR\Resource\Annotation\Link;
8
use Doctrine\Common\Annotations\Reader;
9
use function is_array;
10
use Nocarrier\Hal;
11
12
class HalRenderer implements RenderInterface
13
{
14
    /**
15
     * @var Reader
16
     */
17
    private $reader;
18 1
19
    /**
20 1
     * @var HalLink
21 1
     */
22
    private $link;
23
24
    public function __construct(Reader $reader, HalLink $link)
25
    {
26
        $this->reader = $reader;
27
        $this->link = $link;
28 1
    }
29
30 1
    /**
31
     * {@inheritdoc}
32 1
     */
33 1
    public function render(ResourceObject $ro)
34 1
    {
35
        $this->renderHal($ro);
36 1
        $this->updateHeaders($ro);
37 1
38 1
        return (string) $ro->view;
39
    }
40 1
41
    /**
42
     * {@inheritdoc}
43 1
     *
44
     * @throws \RuntimeException
45 1
     */
46 1
    public function renderHal(ResourceObject $ro)
47
    {
48
        [$ro, $body] = $this->valuate($ro);
0 ignored issues
show
Bug introduced by
The variable $body does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
49
        $method = 'on' . ucfirst($ro->uri->method);
50
        $hasMethod = method_exists($ro, $method);
51
        $annotations = $hasMethod ? $this->reader->getMethodAnnotations(new \ReflectionMethod($ro, $method)) : [];
52
        /* @var $annotations Link[] */
53
        $hal = $this->getHal($ro->uri, $body, $annotations);
54
        $ro->view = $hal->asJson(true) . PHP_EOL;
55
        $ro->headers['Content-Type'] = 'application/hal+json';
56 1
    }
57
58
    private function valuateElements(ResourceObject $ro)
59 1
    {
60
        foreach ($ro->body as $key => &$embeded) {
61
            if ($embeded instanceof AbstractRequest) {
62
                // @codeCoverageIgnoreStart
63
                if ($this->isDifferentSchema($ro, $embeded->resourceObject)) {
64
                    $ro->body['_embedded'][$key] = $embeded()->body;
65
                    unset($ro->body[$key]);
66
67
                    continue;
68
                }
69 1
                // @codeCoverageIgnoreEnd
70
                unset($ro->body[$key]);
71 1
                $view = $this->render($embeded());
72
                $ro->body['_embedded'][$key] = json_decode($view);
73
            }
74 1
        }
75
    }
76 1
77 1
    /**
78 1
     * @codeCoverageIgnore
79 1
     */
80 1
    private function isDifferentSchema(ResourceObject $parentRo, ResourceObject $childRo) : bool
81
    {
82 1
        return $parentRo->uri->scheme . $parentRo->uri->host !== $childRo->uri->scheme . $childRo->uri->host;
83
    }
84
85 1
    private function getReverseMatchedLink(string $uri) : string
86
    {
87
        return $uri;
88 1
    }
89 1
90
    private function getHal(AbstractUri $uri, array $body, array $annotations) : Hal
91
    {
92 1
        $query = $uri->query ? '?' . http_build_query($uri->query) : '';
93 1
        $path = $uri->path . $query;
94
        $selfLink = $this->getReverseMatchedLink($path);
95
        $hal = new Hal($selfLink, $body);
96
97
        return $this->link->addHalLink($body, $annotations, $hal);
98
    }
99 1
100
    private function valuate(ResourceObject $ro) : array
101
    {
102 1
        $ro->body = is_array($ro->body) ? $ro->body : ['value' => $ro->body];
103
        // evaluate all request in body.
104 1
        $this->valuateElements($ro);
105 1
106 1
        return [$ro, $ro->body];
107 1
    }
108 1
109
    private function updateHeaders(ResourceObject $ro)
110
    {
111 1
        $ro->headers['content-type'] = 'application/hal+json';
112
        if (isset($ro->headers['Location'])) {
113
            $ro->headers['Location'] = $this->link->getReverseLink($ro->headers['Location']);
114
        }
115
    }
116
}
117