Completed
Push — master ( 75468d...320ccf )
by Iqbal
03:32
created

SerializerTrait::isInternal()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 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
        $parameters = $constructor->getParameters();
41
42
        if (!empty($parameters)) {
43
            return $reflection->newInstanceArgs(self::buildParameters($parameters, $data));
44
        }
45
46
        return $reflection->newInstance();
47
    }
48
49
    /**
50
     * Build parameters.
51
     *
52
     * @param ReflectionParameter[] $parameters
53
     * @param ParameterBag          $data
54
     *
55
     * @return array
56
     */
57
    protected static function buildParameters(array $parameters, ParameterBag $data)
58
    {
59
        $built = array();
60
        foreach ($parameters as $param) {
61
            $built[] = self::buildValue($param, $data);
62
        }
63
64
        return $built;
65
    }
66
67
    /**
68
     * Build value.
69
     *
70
     * @param ReflectionParameter $parameter
71
     * @param ParameterBag        $data
72
     *
73
     * @return array|mixed|null
74
     */
75
    protected static function buildValue(ReflectionParameter $parameter, ParameterBag $data)
76
    {
77
        $class = $parameter->getClass();
78
        $name = $parameter->getName();
79
        $value = $data->get($name);
80
81
        if (null === $class) {
82
            return self::castType($value, $value, '');
83
        }
84
85
        $value = array_merge($data->all(), (array) $value);
86
87
        return self::buildObjectParameter($class->getName(), $value, $name);
88
    }
89
90
    /**
91
     * Build object parameter.
92
     *
93
     * @param string $class
94
     * @param mixed  $value
95
     * @param string $name
96
     *
97
     * @return mixed|null
98
     */
99
    protected static function buildObjectParameter($class, $value, $name)
100
    {
101
        if (in_array('Borobudur\Cqrs\IdentifierInterface', class_implements($class))) {
102
            if (is_array($value) && isset($value[$name]) && is_string($value[$name])) {
103
                return $class::{'fromString'}($value[$name]);
104
            }
105
        }
106
107
        if (in_array('Borobudur\Cqrs\Serializer\SerializableInterface', class_implements($class))) {
108
            return $class::{'deserialize'}(new ParameterBag($value));
109
        }
110
111
        if ('DateTime' === $class && isset($value[$name])) {
112
            return new DateTime($value[$name]['date'], new DateTimeZone($value[$name]['timezone']));
113
        }
114
115
        return null;
116
    }
117
118
    /**
119
     * {@inheritdoc}
120
     */
121
    public function serialize()
122
    {
123
        $reflection = new ReflectionObject($this);
124
        $properties = $reflection->getProperties();
125
        $data = array();
126
127
        foreach ($properties as $property) {
128
            if ($this->isInternal($property)) {
129
                continue;
130
            }
131
132
            $property->setAccessible(true);
133
            $data[$property->getName()] = $this->normalize($property->getValue($this));
134
        }
135
136
        if ($this instanceof FlatSerializerInterface) {
137
            return $this->resolveFlat($data);
138
        }
139
140
        return $data;
141
    }
142
143
    /**
144
     * Normalize value.
145
     *
146
     * @param $value
147
     *
148
     * @return array|string
149
     */
150
    protected function normalize($value)
151
    {
152
        if ($value instanceof IdentifierInterface) {
153
            return (string) $value;
154
        }
155
156
        if ($value instanceof SerializableInterface) {
157
            return $value->serialize();
158
        }
159
160
        return $value;
161
    }
162
163
    /**
164
     * @param array $data
165
     *
166
     * @return array
167
     */
168
    protected function resolveFlat(array $data)
169
    {
170
        $flat = array();
171
        foreach ($data as $index => $value) {
172
            if (is_array($value)) {
173
                $flat = array_merge($flat, $this->resolveFlat($value));
174
                continue;
175
            }
176
177
            $flat[$index] = $value;
178
        }
179
180
        return $flat;
181
    }
182
183
    /**
184
     * Check if property is internal use (@internal annotation).
185
     *
186
     * @param ReflectionProperty $property
187
     *
188
     * @return bool
189
     */
190
    protected function isInternal(ReflectionProperty $property)
191
    {
192
        return (bool) preg_match('#@internal\n#s', $property->getDocComment());
193
    }
194
}
195