Passed
Push — master ( da3841...78234a )
by Michael
03:01
created

AttributeHandler   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 177
Duplicated Lines 35.03 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 89.66%

Importance

Changes 0
Metric Value
wmc 22
lcom 1
cbo 5
dl 62
loc 177
c 0
b 0
f 0
ccs 52
cts 58
cp 0.8966
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A registerDataTypeHandler() 0 7 2
A toResource() 0 9 2
A processAttributeToResource() 13 13 2
A processTypeToResource() 16 16 3
A processResourceToType() 16 16 3
A processGenericType() 0 16 4
A fromResource() 0 13 3
A processResourceToAttribute() 17 17 3

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
declare(strict_types = 1);
3
4
namespace Mikemirten\Component\JsonApi\Mapper\Handler;
5
6
use Mikemirten\Component\JsonApi\Document\ResourceObject;
7
use Mikemirten\Component\JsonApi\Mapper\Definition\Attribute;
8
use Mikemirten\Component\JsonApi\Mapper\Handler\DataTypeHandler\DataTypeHandlerInterface;
9
use Mikemirten\Component\JsonApi\Mapper\MappingContext;
10
11
/**
12
 * Attribute handler
13
 *
14
 * @package Mikemirten\Component\JsonApi\Mapper\Handler
15
 */
16
class AttributeHandler implements HandlerInterface
17
{
18
    /**
19
     * List of generic types
20
     *
21
     * @var array
22
     */
23
    protected $genericTypes = ['integer', 'float', 'string', 'boolean'];
24
25
    /**
26
     * Data-type handlers
27
     *
28
     * @var DataTypeHandlerInterface[]
29
     */
30
    protected $registeredTypes = [];
31
32
    /**
33
     * Register data-type handler
34
     *
35
     * @param DataTypeHandlerInterface $handler
36
     */
37 2
    public function registerDataTypeHandler(DataTypeHandlerInterface $handler)
38
    {
39 2
        foreach ($handler->supports() as $name)
40
        {
41 2
            $this->registeredTypes[$name] = $handler;
42
        }
43 2
    }
44
45
    /**
46
     * {@inheritdoc}
47
     */
48 4
    public function toResource($object, ResourceObject $resource, MappingContext $context)
49
    {
50 4
        $definitions = $context->getDefinition()->getAttributes();
51
52 4
        foreach ($definitions as $definition)
53
        {
54 4
            $this->processAttributeToResource($object, $resource, $definition);
55
        }
56 3
    }
57
58
    /**
59
     * Process attribute to resource mapping
60
     *
61
     * @param mixed          $object
62
     * @param ResourceObject $resource
63
     * @param Attribute      $definition
64
     */
65 4 View Code Duplication
    protected function processAttributeToResource($object, ResourceObject $resource, Attribute $definition)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
66
    {
67 4
        $name   = $definition->getName();
68 4
        $getter = $definition->getGetter();
69
70 4
        $value = $object->$getter();
71
        
72 4
        if ($definition->hasType()) {
73 3
            $value = $this->processTypeToResource($definition, $value);
74
        }
75
76 3
        $resource->setAttribute($name, $value);
77 3
    }
78
79
    /**
80
     * Process data-type
81
     *
82
     * @param  Attribute $definition
83
     * @param  mixed     $value
84
     * @return mixed
85
     */
86 3 View Code Duplication
    protected function processTypeToResource(Attribute $definition, $value)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
87
    {
88 3
        $type = $definition->getType();
89
90 3
        if (isset($this->registeredTypes[$type])) {
91 1
            $parameters = $definition->getTypeParameters();
92
93 1
            return $this->registeredTypes[$type]->toResource($value, $parameters);
94
        }
95
96 2
        if (in_array($type, $this->genericTypes)) {
97 1
            return $this->processGenericType($type, $value);
98
        }
99
100 1
        throw new \LogicException(sprintf('Unable to handle unknown type "%s" of attribute "%s"', $type, $definition->getName()));
101
    }
102
103
    /**
104
     * Process data-type
105
     *
106
     * @param  Attribute $definition
107
     * @param  mixed     $value
108
     * @return mixed
109
     */
110 2 View Code Duplication
    protected function processResourceToType(Attribute $definition, $value)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
111
    {
112 2
        $type = $definition->getType();
113
114 2
        if (isset($this->registeredTypes[$type])) {
115 1
            $parameters = $definition->getTypeParameters();
116
117 1
            return $this->registeredTypes[$type]->fromResource($value, $parameters);
118
        }
119
120 1
        if (in_array($type, $this->genericTypes)) {
121 1
            return $this->processGenericType($type, $value);
122
        }
123
124
        throw new \LogicException(sprintf('Unable to handle unknown type "%s" of attribute "%s"', $type, $definition->getName()));
125
    }
126
127
    /**
128
     * Process generic data-types
129
     *
130
     * @param  string $type
131
     * @param  mixed  $value
132
     * @return bool|float|int|string
133
     */
134 2
    protected function processGenericType(string $type, $value)
135
    {
136 2
        if ($type === 'integer') {
137
            return (int) $value;
138
        }
139
140 2
        if ($type === 'float') {
141
            return (float) $value;
142
        }
143
144 2
        if ($type === 'bool') {
145
            return (bool) $value;
146
        }
147
148 2
        return (string) $value;
149
    }
150
151
    /**
152
     * {@inheritdoc}
153
     */
154 3
    public function fromResource($object, ResourceObject $resource, MappingContext $context)
155
    {
156 3
        $definitions = $context->getDefinition()->getAttributes();
157
158 3
        foreach ($definitions as $definition)
159
        {
160 3
            if (! $definition->hasSetter()) {
161
                continue;
162
            }
163
164 3
            $this->processResourceToAttribute($object, $resource, $definition);
165
        }
166 3
    }
167
168
    /**
169
     * Process resource to attribute mapping
170
     *
171
     * @param mixed          $object
172
     * @param ResourceObject $resource
173
     * @param Attribute      $definition
174
     */
175 3 View Code Duplication
    protected function processResourceToAttribute($object, ResourceObject $resource, Attribute $definition)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
176
    {
177 3
        $name = $definition->getName();
178
179 3
        if (! $resource->hasAttribute($name)) {
180
            return;
181
        }
182
183 3
        $value  = $resource->getAttribute($name);
184 3
        $setter = $definition->getSetter();
185
186 3
        if ($definition->hasType()) {
187 2
            $value = $this->processResourceToType($definition, $value);
188
        }
189
190 3
        $object->$setter($value);
191
    }
192
}