Passed
Push — master ( 20fa94...bcb279 )
by Michael
02:03
created

DocumentBuilder::createSingleResourceDocument()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 13
ccs 7
cts 7
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 7
nc 2
nop 1
crap 2
1
<?php
2
declare(strict_types = 1);
3
4
namespace Mikemirten\Bundle\JsonApiBundle\Builder;
5
6
use Mikemirten\Component\JsonApi\Mapper\Handler\LinkRepository\RepositoryProvider;
7
use Mikemirten\Component\JsonApi\Mapper\ObjectMapper;
8
use Mikemirten\Bundle\JsonApiBundle\Response\{
9
    Behaviour\IncludedObjectsAwareInterface,
10
    AbstractJsonApiView,
11
    JsonApiIteratorView,
12
    JsonApiObjectView
13
};
14
use Mikemirten\Component\JsonApi\Document\{
15
    AbstractDocument,
16
    SingleResourceDocument,
17
    ResourceCollectionDocument,
18
    ResourceObject,
19
    JsonApiObject,
20
    LinkObject
21
};
22
23
/**
24
 * JSON API Document builder
25
 *
26
 * @package DocumentBuilder
27
 */
28
class DocumentBuilder
29
{
30
    /**
31
     * @var ObjectMapper
32
     */
33
    protected $mapper;
34
35
    /**
36
     * Link-repositories provider
37
     *
38
     * @var RepositoryProvider
39
     */
40
    protected $repositoryProvider;
41
42
    /**
43
     * Builder constructor.
44
     *
45
     * @param ObjectMapper       $mapper
46
     * @param RepositoryProvider $repositoryProvider
47
     */
48 10
    public function __construct(ObjectMapper $mapper, RepositoryProvider $repositoryProvider)
49
    {
50 10
        $this->mapper             = $mapper;
51 10
        $this->repositoryProvider = $repositoryProvider;
52 10
    }
53
54
    /**
55
     * Build a document by a view
56
     *
57
     * @param  AbstractJsonApiView $view
58
     * @return AbstractDocument
59
     */
60 9
    public function build(AbstractJsonApiView $view): AbstractDocument
61
    {
62 9
        $document = $this->createDocument($view);
63
64 9
        $this->handleIncludedResources($document, $view);
65 9
        $this->handleDocumentLinks($document, $view);
66
67 9
        if ($view->hasDocumentCallback()) {
68 2
            ($view->getDocumentCallback())($document);
69
        }
70
71 9
        return $document;
72
    }
73
74
    /**
75
     * Create a document by a view
76
     *
77
     * @param  AbstractJsonApiView $view
78
     * @return AbstractDocument
79
     */
80 9
    protected function createDocument(AbstractJsonApiView $view): AbstractDocument
81
    {
82 9
        if ($view instanceof JsonApiObjectView) {
83 5
            return $this->createSingleResourceDocument($view);
84
        }
85
86 4
        if ($view instanceof JsonApiIteratorView) {
87 4
            return $this->createCollectionDocument($view);
88
        }
89
90
        throw new \LogicException('Unknown extension of AbstractJsonApiView cannot be processed: ' . get_class($view));
91
    }
92
93
    /**
94
     * Handle single object Json API view
95
     *
96
     * @param  JsonApiObjectView $view
97
     * @return SingleResourceDocument
98
     */
99 5
    protected function createSingleResourceDocument(JsonApiObjectView $view): SingleResourceDocument
100
    {
101 5
        $resource = $this->handleObject($view->getObject());
102
103 5
        if ($view->hasResourceCallback()) {
104 1
            ($view->getResourceCallback())($resource);
105
        }
106
107 5
        $document = new SingleResourceDocument($resource);
108 5
        $document->setJsonApi(new JsonApiObject());
109
110 5
        return $document;
111
    }
112
113
    /**
114
     * Handle object-iterator
115
     *
116
     * @param  JsonApiIteratorView $view
117
     * @return ResourceCollectionDocument
118
     */
119 4
    protected function createCollectionDocument(JsonApiIteratorView $view): ResourceCollectionDocument
120
    {
121 4
        $document = new ResourceCollectionDocument();
122 4
        $document->setJsonApi(new JsonApiObject());
123
124 4
        foreach ($view as $object)
125
        {
126 3
            $resource = $this->handleObject($object);
127
128 3
            if ($view->hasResourceCallback()) {
129 1
                ($view->getResourceCallback())($resource);
130
            }
131
132 3
            $document->addResource($resource);
133
        }
134
135 4
        return $document;
136
    }
137
138
    /**
139
     * Handle object
140
     *
141
     * @param  $object
142
     * @return ResourceObject
143
     */
144 9
    protected function handleObject($object): ResourceObject
145
    {
146 9
        if ($object instanceof ResourceObject) {
147
            return $object;
148
        }
149
150 9
        return $this->mapper->toResource($object);
151
    }
152
153
    /**
154
     * Handle supposed to be included to document resources
155
     *
156
     * @param AbstractDocument              $document
157
     * @param IncludedObjectsAwareInterface $view
158
     */
159 9
    protected function handleIncludedResources(AbstractDocument $document, IncludedObjectsAwareInterface $view)
160
    {
161 9
        foreach ($view->getIncludedObjects() as $object)
162
        {
163 2
            $resource = $this->handleObject($object);
164 2
            $document->addIncludedResource($resource);
165
        }
166 9
    }
167
168
    /**
169
     * Handle links of document
170
     *
171
     * @param AbstractJsonApiView $view
172
     * @param AbstractDocument    $document
173
     */
174 9
    protected function handleDocumentLinks(AbstractDocument $document, AbstractJsonApiView $view)
175
    {
176 9
        foreach ($view->getDocumentLinks() as $definition)
177
        {
178 1
            $repositoryName = $definition->getRepositoryName();
179 1
            $linkName       = $definition->getLinkName();
180 1
            $parameters     = $definition->getParameters();
181
182 1
            $linkData = $this->repositoryProvider
183 1
                ->getRepository($repositoryName)
184 1
                ->getLink($linkName, $parameters);
185
186 1
            $metadata = array_replace(
187 1
                $linkData->getMetadata(),
188 1
                $definition->getMetadata()
189
            );
190
191 1
            $link = new LinkObject($linkData->getReference(), $metadata);
192
193 1
            $document->setLink($definition->getName(), $link);
194
        }
195
    }
196
}