SerializerTrait   A
last analyzed

Complexity

Total Complexity 30

Size/Duplication

Total Lines 183
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
wmc 30
lcom 1
cbo 3
dl 0
loc 183
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A deserialize() 0 15 3
A buildParameters() 0 9 2
A buildValue() 0 14 2
D buildObjectParameter() 0 26 9
A serialize() 0 21 4
B normalize() 0 16 6
A resolveFlat() 0 14 3
A isInternal() 0 4 1
1
<?php
2
/*
3
 * This file is part of the Borobudur-Cqrs package.
4
 *
5
 * (c) Hexacodelabs <http://hexacodelabs.com>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Borobudur\Cqrs\Serializer;
12
13
use Borobudur\Cqrs\IdentifierInterface;
14
use Borobudur\Cqrs\ParameterBag;
15
use DateTime;
16
use DateTimeZone;
17
use ReflectionClass;
18
use ReflectionObject;
19
use ReflectionParameter;
20
use ReflectionProperty;
21
22
/**
23
 * @author      Iqbal Maulana <[email protected]>
24
 * @created     8/18/15
25
 */
26
trait SerializerTrait
27
{
28
    use DataTypeCasterTrait;
29
30
    /**
31
     * {@inheritdoc}
32
     *
33
     * @return static
34
     */
35
    public static function deserialize(ParameterBag $data)
36
    {
37
        $class = get_called_class();
38
        $reflection = new ReflectionClass($class);
39
        $constructor = $reflection->getConstructor();
40
41
        if (null !== $constructor) {
42
            $parameters = $constructor->getParameters();
43
            if (!empty($parameters)) {
44
                return $reflection->newInstanceArgs(self::buildParameters($parameters, $data));
45
            }
46
        }
47
48
        return $reflection->newInstance();
49
    }
50
51
    /**
52
     * Build parameters.
53
     *
54
     * @param ReflectionParameter[] $parameters
55
     * @param ParameterBag          $data
56
     *
57
     * @return array
58
     */
59
    protected static function buildParameters(array $parameters, ParameterBag $data)
60
    {
61
        $built = array();
62
        foreach ($parameters as $param) {
63
            $built[] = self::buildValue($param, $data);
64
        }
65
66
        return $built;
67
    }
68
69
    /**
70
     * Build value.
71
     *
72
     * @param ReflectionParameter $parameter
73
     * @param ParameterBag        $data
74
     *
75
     * @return array|mixed|null
76
     */
77
    protected static function buildValue(ReflectionParameter $parameter, ParameterBag $data)
78
    {
79
        $class = $parameter->getClass();
80
        $name = $parameter->getName();
81
        $value = $data->get($name);
82
83
        if (null === $class) {
84
            return self::castType($value, $value, '');
85
        }
86
87
        $value = array_merge($data->all(), (array) $value);
88
89
        return self::buildObjectParameter($class, $value, $name);
90
    }
91
92
    /**
93
     * Build object parameter.
94
     *
95
     * @param ReflectionClass $class
96
     * @param mixed           $value
97
     * @param string          $name
98
     *
99
     * @return mixed|null
100
     */
101
    protected static function buildObjectParameter(ReflectionClass $class, $value, $name)
102
    {
103
        $className = $class->getName();
104
105
        if (in_array('Borobudur\Cqrs\IdentifierInterface', class_implements($className))) {
106
            if (is_array($value) && isset($value[$name]) && is_string($value[$name])) {
107
                return $className::{'fromString'}($value[$name]);
108
            }
109
        }
110
111
        if (in_array('Borobudur\Cqrs\Serializer\SerializableInterface', class_implements($className))) {
112
            return $className::{'deserialize'}(new ParameterBag($value));
113
        }
114
115
        if ('DateTime' === $className && isset($value[$name])) {
116
            $value[$name] = (array) $value[$name];
117
118
            return new DateTime($value[$name]['date'], new DateTimeZone($value[$name]['timezone']));
119
        }
120
121
        if ($class->hasMethod('__toString')) {
122
            return new $className($value[$name]);
123
        }
124
125
        return null;
126
    }
127
128
    /**
129
     * {@inheritdoc}
130
     */
131
    public function serialize()
132
    {
133
        $reflection = new ReflectionObject($this);
134
        $properties = $reflection->getProperties();
135
        $data = array();
136
137
        foreach ($properties as $property) {
138
            if ($this->isInternal($property)) {
139
                continue;
140
            }
141
142
            $property->setAccessible(true);
143
            $data[$property->getName()] = $this->normalize($property->getValue($this));
144
        }
145
146
        if ($this instanceof FlatSerializerInterface) {
147
            return $this->resolveFlat($data);
0 ignored issues
show
Bug introduced by
The method resolveFlat() does not seem to exist on object<Borobudur\Cqrs\Se...latSerializerInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
148
        }
149
150
        return $data;
151
    }
152
153
    /**
154
     * Normalize value.
155
     *
156
     * @param $value
157
     *
158
     * @return array|string
159
     */
160
    protected function normalize($value)
161
    {
162
        if ($value instanceof IdentifierInterface) {
163
            return (string) $value;
164
        }
165
166
        if ($value instanceof SerializableInterface) {
167
            return $value->serialize();
168
        }
169
170
        if (is_object($value) && method_exists($value, '__toString') && !$value instanceof \SplFileInfo) {
171
            return (string) $value;
172
        }
173
174
        return $value;
175
    }
176
177
    /**
178
     * @param array $data
179
     *
180
     * @return array
181
     */
182
    protected function resolveFlat(array $data)
183
    {
184
        $flat = array();
185
        foreach ($data as $index => $value) {
186
            if (is_array($value)) {
187
                $flat = array_merge($flat, $this->resolveFlat($value));
188
                continue;
189
            }
190
191
            $flat[$index] = $value;
192
        }
193
194
        return $flat;
195
    }
196
197
    /**
198
     * Check if property is internal use (@internal annotation).
199
     *
200
     * @param ReflectionProperty $property
201
     *
202
     * @return bool
203
     */
204
    protected function isInternal(ReflectionProperty $property)
205
    {
206
        return (bool) preg_match('#@internal\n#s', $property->getDocComment());
207
    }
208
}
209