Completed
Push — spike ( 5bf55a )
by Akihito
05:15 queued 03:49
created

HalRenderer   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 102
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 76%

Importance

Changes 0
Metric Value
wmc 18
lcom 1
cbo 6
dl 0
loc 102
ccs 38
cts 50
cp 0.76
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A render() 0 14 2
A isDifferentSchema() 0 4 1
A getReverseMatchedLink() 0 4 1
A getHal() 0 10 2
A valuate() 0 16 4
A addLinks() 0 10 3
A valuateElements() 0 17 4
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 Nocarrier\Hal;
10
11
class HalRenderer implements RenderInterface
12
{
13
    /**
14
     * @var Reader
15
     */
16
    private $reader;
17
18 1
    public function __construct(Reader $reader)
19
    {
20 1
        $this->reader = $reader;
21 1
    }
22
23
    /**
24
     * {@inheritdoc}
25
     *
26
     * @throws \RuntimeException
27
     */
28 1
    public function render(ResourceObject $ro)
29
    {
30 1
        list($ro, $body) = $this->valuate($ro);
31
32 1
        $method = 'on' . ucfirst($ro->uri->method);
33 1
        $hasMethod = method_exists($ro, $method);
34 1
        $annotations = $hasMethod ? $this->reader->getMethodAnnotations(new \ReflectionMethod($ro, $method)) : [];
35
        /* @var $annotations Link[] */
36 1
        $hal = $this->getHal($ro->uri, $body, $annotations);
37 1
        $ro->view = $hal->asJson(true) . PHP_EOL;
38 1
        $ro->headers['Content-Type'] = 'application/hal+json';
39
40 1
        return $ro->view;
41
    }
42
43 1
    private function valuateElements(ResourceObject &$ro)
44
    {
45 1
        foreach ($ro->body as $key => &$embeded) {
46 1
            if ($embeded instanceof AbstractRequest) {
47
                $isDefferentSchema = $this->isDifferentSchema($ro, $embeded->resourceObject);
48
                if ($isDefferentSchema === true) {
49
                    $ro->body['_embedded'][$key] = $embeded()->body;
50
                    unset($ro->body[$key]);
51
52
                    continue;
53
                }
54
                unset($ro->body[$key]);
55
                $view = $this->render($embeded());
56
                $ro->body['_embedded'][$key] = json_decode($view);
57
            }
58
        }
59 1
    }
60
61
    /**
62
     * Return "is different schema" (page <-> app)
63
     */
64
    private function isDifferentSchema(ResourceObject $parentRo, ResourceObject $childRo) : bool
65
    {
66
        return $parentRo->uri->scheme . $parentRo->uri->host !== $childRo->uri->scheme . $childRo->uri->host;
67
    }
68
69 1
    private function getReverseMatchedLink(string $uri) : string
70
    {
71 1
        return $uri;
72
    }
73
74 1
    private function getHal(AbstractUri $uri, array $body, array $annotations) : Hal
75
    {
76 1
        $query = $uri->query ? '?' . http_build_query($uri->query) : '';
77 1
        $path = $uri->path . $query;
78 1
        $selfLink = $this->getReverseMatchedLink($path);
79 1
        $hal = new Hal($selfLink, $body);
80 1
        $this->addLinks($body, $annotations, $hal);
81
82 1
        return $hal;
83
    }
84
85 1
    private function valuate(ResourceObject $ro) : array
86
    {
87
        // evaluate all request in body.
88 1
        if (is_array($ro->body)) {
89 1
            $this->valuateElements($ro);
90
        }
91
        // HAL
92 1
        $body = $ro->body ?: [];
93 1
        if (is_scalar($body)) {
94
            $body = ['value' => $body];
95
96
            return [$ro, $body];
97
        }
98
99 1
        return[$ro, (array) $body];
100
    }
101
102 1
    private function addLinks(array $body, array $annotations, Hal $hal)
103
    {
104 1
        foreach ($annotations as $annotation) {
105 1
            if ($annotation instanceof Link) {
106 1
                $uri = uri_template($annotation->href, $body);
107 1
                $reverseUri = $this->getReverseMatchedLink($uri);
108 1
                $hal->addLink($annotation->rel, $reverseUri);
109
            }
110
        }
111 1
    }
112
}
113