Passed
Push — master ( 71a3af...64594b )
by Michael
02:24
created

DocumentHydrator   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 137
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 97.56%

Importance

Changes 0
Metric Value
wmc 17
lcom 1
cbo 6
dl 0
loc 137
ccs 40
cts 41
cp 0.9756
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A registerExtension() 0 7 2
A hydrate() 0 16 4
A hydrateObject() 0 9 3
A processNoDataDocument() 0 8 1
A processSingleResourceDocument() 0 9 1
A processResourceCollectionDocument() 0 13 2
A hydrateResource() 0 18 4
1
<?php
2
declare(strict_types = 1);
3
4
namespace Mikemirten\Component\JsonApi\Hydrator;
5
6
use Mikemirten\Component\JsonApi\Document\AbstractDocument;
7
use Mikemirten\Component\JsonApi\Document\NoDataDocument;
8
use Mikemirten\Component\JsonApi\Document\ResourceCollectionDocument;
9
use Mikemirten\Component\JsonApi\Document\ResourceObject;
10
use Mikemirten\Component\JsonApi\Document\SingleResourceDocument;
11
use Mikemirten\Component\JsonApi\Exception\InvalidDocumentException;
12
use Mikemirten\Component\JsonApi\Hydrator\Extension\ExtensionInterface;
13
14
/**
15
 * Json API Document hydrator
16
 * Supports base set of members, others supposed to be supported by extensions (handlers) registered in the hydrator.
17
 *
18
 * @see http://jsonapi.org/format/#document-structure
19
 *
20
 * @package Mikemirten\Component\JsonApi\Hydrator
21
 */
22
class DocumentHydrator
23
{
24
    /**
25
     * Section handlers
26
     *
27
     * @var ExtensionInterface[]
28
     */
29
    protected $extensions = [];
30
31
    /**
32
     * Register extension
33
     *
34
     * @param ExtensionInterface $extension
35
     */
36 1
    public function registerExtension(ExtensionInterface $extension)
37
    {
38 1
        foreach ($extension->supports() as $section)
39
        {
40 1
            $this->extensions[$section] = $extension;
41
        }
42 1
    }
43
44
    /**
45
     * Hydrate source to a document
46
     *
47
     * @param  object $source
48
     * @return AbstractDocument
49
     */
50 7
    public function hydrate($source): AbstractDocument
51
    {
52 7
        if (! isset($source->data)) {
53 2
            return $this->processNoDataDocument($source);
54
        }
55
56 5
        if (is_object($source->data)) {
57 3
            return $this->processSingleResourceDocument($source);
58
        }
59
60 2
        if (is_array($source->data)) {
61 2
            return $this->processResourceCollectionDocument($source);
62
        }
63
64
        throw new InvalidDocumentException('If data is present and is not null it must be an object or an array');
65
    }
66
67
    /**
68
     * Hydrate object (part of document)
69
     *
70
     * @param  mixed $object Object for hydration
71
     * @param  mixed $source Source of data
72
     */
73 5
    public function hydrateObject($object, $source)
74
    {
75 5
        foreach ($source as $name => $section)
76
        {
77 4
            if (isset($this->extensions[$name])) {
78 4
                $this->extensions[$name]->hydrate($object, $section, $this);
79
            }
80
        }
81 5
    }
82
83
    /**
84
     * Process document contains no data
85
     *
86
     * @param  mixed $source
87
     * @return NoDataDocument
88
     */
89 2
    protected function processNoDataDocument($source): NoDataDocument
90
    {
91 2
        $document = new NoDataDocument();
92
93 2
        $this->hydrateObject($document, $source);
94
95 2
        return $document;
96
    }
97
98
    /**
99
     * Process document with single resource
100
     *
101
     * @param  mixed $source
102
     * @return SingleResourceDocument
103
     */
104 3
    protected function processSingleResourceDocument($source): SingleResourceDocument
105
    {
106 3
        $resource = $this->hydrateResource($source->data);
107 1
        $document = new SingleResourceDocument($resource);
108
109 1
        $this->hydrateObject($document, $source);
110
111 1
        return $document;
112
    }
113
114
    /**
115
     * Process document with collection of resources
116
     *
117
     * @param  mixed $source
118
     * @return ResourceCollectionDocument
119
     */
120 2
    protected function processResourceCollectionDocument($source): ResourceCollectionDocument
121
    {
122 2
        $document = new ResourceCollectionDocument();
123
124 2
        foreach ($source->data as $resourceSrc)
125
        {
126 1
            $document->addResource($this->hydrateResource($resourceSrc));
127
        }
128
129 2
        $this->hydrateObject($document, $source);
130
131 2
        return $document;
132
    }
133
134
    /**
135
     * Create resource
136
     *
137
     * @param  mixed $source
138
     * @return ResourceObject
139
     */
140 4
    public function hydrateResource($source): ResourceObject
141
    {
142 4
        if (! isset($source->id)) {
143 1
            throw new InvalidDocumentException('Resource contains no ID');
144
        }
145
146 3
        if (! isset($source->type)) {
147 1
            throw new InvalidDocumentException('Resource contains no type');
148
        }
149
150 2
        $attributes = empty($source->attributes) ? [] : get_object_vars($source->attributes);
151
152 2
        $resource = new ResourceObject($source->id, $source->type, $attributes);
153
154 2
        $this->hydrateObject($resource, $source);
155
156 2
        return $resource;
157
    }
158
}